user-manual: Fix 'both: so' -> 'both; so' typo
[git/jnareb-git.git] / t / t3510-cherry-pick-sequence.sh
blob7b7a89dbd5ce578e0a722345a00f247e383689ef
1 #!/bin/sh
3 test_description='Test cherry-pick continuation features
5 + conflicting: rewrites unrelated to conflicting
6 + yetanotherpick: rewrites foo to e
7 + anotherpick: rewrites foo to d
8 + picked: rewrites foo to c
9 + unrelatedpick: rewrites unrelated to reallyunrelated
10 + base: rewrites foo to b
11 + initial: writes foo as a, unrelated as unrelated
15 . ./test-lib.sh
17 # Repeat first match 10 times
18 _r10='\1\1\1\1\1\1\1\1\1\1'
20 pristine_detach () {
21 git cherry-pick --quit &&
22 git checkout -f "$1^0" &&
23 git read-tree -u --reset HEAD &&
24 git clean -d -f -f -q -x
27 test_expect_success setup '
28 git config advice.detachedhead false &&
29 echo unrelated >unrelated &&
30 git add unrelated &&
31 test_commit initial foo a &&
32 test_commit base foo b &&
33 test_commit unrelatedpick unrelated reallyunrelated &&
34 test_commit picked foo c &&
35 test_commit anotherpick foo d &&
36 test_commit yetanotherpick foo e &&
37 pristine_detach initial &&
38 test_commit conflicting unrelated
41 test_expect_success 'cherry-pick persists data on failure' '
42 pristine_detach initial &&
43 test_expect_code 1 git cherry-pick -s base..anotherpick &&
44 test_path_is_dir .git/sequencer &&
45 test_path_is_file .git/sequencer/head &&
46 test_path_is_file .git/sequencer/todo &&
47 test_path_is_file .git/sequencer/opts
50 test_expect_success 'cherry-pick mid-cherry-pick-sequence' '
51 pristine_detach initial &&
52 test_must_fail git cherry-pick base..anotherpick &&
53 test_cmp_rev picked CHERRY_PICK_HEAD &&
54 # "oops, I forgot that these patches rely on the change from base"
55 git checkout HEAD foo &&
56 git cherry-pick base &&
57 git cherry-pick picked &&
58 git cherry-pick --continue &&
59 git diff --exit-code anotherpick
62 test_expect_success 'cherry-pick persists opts correctly' '
63 pristine_detach initial &&
64 test_expect_code 128 git cherry-pick -s -m 1 --strategy=recursive -X patience -X ours initial..anotherpick &&
65 test_path_is_dir .git/sequencer &&
66 test_path_is_file .git/sequencer/head &&
67 test_path_is_file .git/sequencer/todo &&
68 test_path_is_file .git/sequencer/opts &&
69 echo "true" >expect &&
70 git config --file=.git/sequencer/opts --get-all options.signoff >actual &&
71 test_cmp expect actual &&
72 echo "1" >expect &&
73 git config --file=.git/sequencer/opts --get-all options.mainline >actual &&
74 test_cmp expect actual &&
75 echo "recursive" >expect &&
76 git config --file=.git/sequencer/opts --get-all options.strategy >actual &&
77 test_cmp expect actual &&
78 cat >expect <<-\EOF &&
79 patience
80 ours
81 EOF
82 git config --file=.git/sequencer/opts --get-all options.strategy-option >actual &&
83 test_cmp expect actual
86 test_expect_success 'cherry-pick cleans up sequencer state upon success' '
87 pristine_detach initial &&
88 git cherry-pick initial..picked &&
89 test_path_is_missing .git/sequencer
92 test_expect_success '--quit does not complain when no cherry-pick is in progress' '
93 pristine_detach initial &&
94 git cherry-pick --quit
97 test_expect_success '--abort requires cherry-pick in progress' '
98 pristine_detach initial &&
99 test_must_fail git cherry-pick --abort
102 test_expect_success '--quit cleans up sequencer state' '
103 pristine_detach initial &&
104 test_expect_code 1 git cherry-pick base..picked &&
105 git cherry-pick --quit &&
106 test_path_is_missing .git/sequencer
109 test_expect_success '--quit keeps HEAD and conflicted index intact' '
110 pristine_detach initial &&
111 cat >expect <<-\EOF &&
112 OBJID
113 :100644 100644 OBJID OBJID M unrelated
114 OBJID
115 :000000 100644 OBJID OBJID A foo
116 :000000 100644 OBJID OBJID A unrelated
118 test_expect_code 1 git cherry-pick base..picked &&
119 git cherry-pick --quit &&
120 test_path_is_missing .git/sequencer &&
121 test_must_fail git update-index --refresh &&
123 git rev-list HEAD |
124 git diff-tree --root --stdin |
125 sed "s/$_x40/OBJID/g"
126 } >actual &&
127 test_cmp expect actual
130 test_expect_success '--abort to cancel multiple cherry-pick' '
131 pristine_detach initial &&
132 test_expect_code 1 git cherry-pick base..anotherpick &&
133 git cherry-pick --abort &&
134 test_path_is_missing .git/sequencer &&
135 test_cmp_rev initial HEAD &&
136 git update-index --refresh &&
137 git diff-index --exit-code HEAD
140 test_expect_success '--abort to cancel single cherry-pick' '
141 pristine_detach initial &&
142 test_expect_code 1 git cherry-pick picked &&
143 git cherry-pick --abort &&
144 test_path_is_missing .git/sequencer &&
145 test_cmp_rev initial HEAD &&
146 git update-index --refresh &&
147 git diff-index --exit-code HEAD
150 test_expect_success 'cherry-pick --abort to cancel multiple revert' '
151 pristine_detach anotherpick &&
152 test_expect_code 1 git revert base..picked &&
153 git cherry-pick --abort &&
154 test_path_is_missing .git/sequencer &&
155 test_cmp_rev anotherpick HEAD &&
156 git update-index --refresh &&
157 git diff-index --exit-code HEAD
160 test_expect_success 'revert --abort works, too' '
161 pristine_detach anotherpick &&
162 test_expect_code 1 git revert base..picked &&
163 git revert --abort &&
164 test_path_is_missing .git/sequencer &&
165 test_cmp_rev anotherpick HEAD
168 test_expect_success '--abort to cancel single revert' '
169 pristine_detach anotherpick &&
170 test_expect_code 1 git revert picked &&
171 git revert --abort &&
172 test_path_is_missing .git/sequencer &&
173 test_cmp_rev anotherpick HEAD &&
174 git update-index --refresh &&
175 git diff-index --exit-code HEAD
178 test_expect_success '--abort keeps unrelated change, easy case' '
179 pristine_detach unrelatedpick &&
180 echo changed >expect &&
181 test_expect_code 1 git cherry-pick picked..yetanotherpick &&
182 echo changed >unrelated &&
183 git cherry-pick --abort &&
184 test_cmp expect unrelated
187 test_expect_success '--abort refuses to clobber unrelated change, harder case' '
188 pristine_detach initial &&
189 echo changed >expect &&
190 test_expect_code 1 git cherry-pick base..anotherpick &&
191 echo changed >unrelated &&
192 test_must_fail git cherry-pick --abort &&
193 test_cmp expect unrelated &&
194 git rev-list HEAD >log &&
195 test_line_count = 2 log &&
196 test_must_fail git update-index --refresh &&
198 git checkout unrelated &&
199 git cherry-pick --abort &&
200 test_cmp_rev initial HEAD
203 test_expect_success 'cherry-pick still writes sequencer state when one commit is left' '
204 pristine_detach initial &&
205 test_expect_code 1 git cherry-pick base..picked &&
206 test_path_is_dir .git/sequencer &&
207 echo "resolved" >foo &&
208 git add foo &&
209 git commit &&
211 git rev-list HEAD |
212 git diff-tree --root --stdin |
213 sed "s/$_x40/OBJID/g"
214 } >actual &&
215 cat >expect <<-\EOF &&
216 OBJID
217 :100644 100644 OBJID OBJID M foo
218 OBJID
219 :100644 100644 OBJID OBJID M unrelated
220 OBJID
221 :000000 100644 OBJID OBJID A foo
222 :000000 100644 OBJID OBJID A unrelated
224 test_cmp expect actual
227 test_expect_success '--abort after last commit in sequence' '
228 pristine_detach initial &&
229 test_expect_code 1 git cherry-pick base..picked &&
230 git cherry-pick --abort &&
231 test_path_is_missing .git/sequencer &&
232 test_cmp_rev initial HEAD &&
233 git update-index --refresh &&
234 git diff-index --exit-code HEAD
237 test_expect_success 'cherry-pick does not implicitly stomp an existing operation' '
238 pristine_detach initial &&
239 test_expect_code 1 git cherry-pick base..anotherpick &&
240 test-chmtime -v +0 .git/sequencer >expect &&
241 test_expect_code 128 git cherry-pick unrelatedpick &&
242 test-chmtime -v +0 .git/sequencer >actual &&
243 test_cmp expect actual
246 test_expect_success '--continue complains when no cherry-pick is in progress' '
247 pristine_detach initial &&
248 test_expect_code 128 git cherry-pick --continue
251 test_expect_success '--continue complains when there are unresolved conflicts' '
252 pristine_detach initial &&
253 test_expect_code 1 git cherry-pick base..anotherpick &&
254 test_expect_code 128 git cherry-pick --continue
257 test_expect_success '--continue of single cherry-pick' '
258 pristine_detach initial &&
259 echo c >expect &&
260 test_must_fail git cherry-pick picked &&
261 echo c >foo &&
262 git add foo &&
263 git cherry-pick --continue &&
265 test_cmp expect foo &&
266 test_cmp_rev initial HEAD^ &&
267 git diff --exit-code HEAD &&
268 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
271 test_expect_success '--continue of single revert' '
272 pristine_detach initial &&
273 echo resolved >expect &&
274 echo "Revert \"picked\"" >expect.msg &&
275 test_must_fail git revert picked &&
276 echo resolved >foo &&
277 git add foo &&
278 git cherry-pick --continue &&
280 git diff --exit-code HEAD &&
281 test_cmp expect foo &&
282 test_cmp_rev initial HEAD^ &&
283 git diff-tree -s --pretty=tformat:%s HEAD >msg &&
284 test_cmp expect.msg msg &&
285 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
286 test_must_fail git rev-parse --verify REVERT_HEAD
289 test_expect_success '--continue after resolving conflicts' '
290 pristine_detach initial &&
291 echo d >expect &&
292 cat >expect.log <<-\EOF &&
293 OBJID
294 :100644 100644 OBJID OBJID M foo
295 OBJID
296 :100644 100644 OBJID OBJID M foo
297 OBJID
298 :100644 100644 OBJID OBJID M unrelated
299 OBJID
300 :000000 100644 OBJID OBJID A foo
301 :000000 100644 OBJID OBJID A unrelated
303 test_must_fail git cherry-pick base..anotherpick &&
304 echo c >foo &&
305 git add foo &&
306 git cherry-pick --continue &&
308 git rev-list HEAD |
309 git diff-tree --root --stdin |
310 sed "s/$_x40/OBJID/g"
311 } >actual.log &&
312 test_cmp expect foo &&
313 test_cmp expect.log actual.log
316 test_expect_success '--continue after resolving conflicts and committing' '
317 pristine_detach initial &&
318 test_expect_code 1 git cherry-pick base..anotherpick &&
319 echo "c" >foo &&
320 git add foo &&
321 git commit &&
322 git cherry-pick --continue &&
323 test_path_is_missing .git/sequencer &&
325 git rev-list HEAD |
326 git diff-tree --root --stdin |
327 sed "s/$_x40/OBJID/g"
328 } >actual &&
329 cat >expect <<-\EOF &&
330 OBJID
331 :100644 100644 OBJID OBJID M foo
332 OBJID
333 :100644 100644 OBJID OBJID M foo
334 OBJID
335 :100644 100644 OBJID OBJID M unrelated
336 OBJID
337 :000000 100644 OBJID OBJID A foo
338 :000000 100644 OBJID OBJID A unrelated
340 test_cmp expect actual
343 test_expect_success '--continue asks for help after resolving patch to nil' '
344 pristine_detach conflicting &&
345 test_must_fail git cherry-pick initial..picked &&
347 test_cmp_rev unrelatedpick CHERRY_PICK_HEAD &&
348 git checkout HEAD -- unrelated &&
349 test_must_fail git cherry-pick --continue 2>msg &&
350 test_i18ngrep "The previous cherry-pick is now empty" msg
353 test_expect_success 'follow advice and skip nil patch' '
354 pristine_detach conflicting &&
355 test_must_fail git cherry-pick initial..picked &&
357 git checkout HEAD -- unrelated &&
358 test_must_fail git cherry-pick --continue &&
359 git reset &&
360 git cherry-pick --continue &&
362 git rev-list initial..HEAD >commits &&
363 test_line_count = 3 commits
366 test_expect_success '--continue respects opts' '
367 pristine_detach initial &&
368 test_expect_code 1 git cherry-pick -x base..anotherpick &&
369 echo "c" >foo &&
370 git add foo &&
371 git commit &&
372 git cherry-pick --continue &&
373 test_path_is_missing .git/sequencer &&
374 git cat-file commit HEAD >anotherpick_msg &&
375 git cat-file commit HEAD~1 >picked_msg &&
376 git cat-file commit HEAD~2 >unrelatedpick_msg &&
377 git cat-file commit HEAD~3 >initial_msg &&
378 test_must_fail grep "cherry picked from" initial_msg &&
379 grep "cherry picked from" unrelatedpick_msg &&
380 grep "cherry picked from" picked_msg &&
381 grep "cherry picked from" anotherpick_msg
384 test_expect_success '--continue of single-pick respects -x' '
385 pristine_detach initial &&
386 test_must_fail git cherry-pick -x picked &&
387 echo c >foo &&
388 git add foo &&
389 git cherry-pick --continue &&
390 test_path_is_missing .git/sequencer &&
391 git cat-file commit HEAD >msg &&
392 grep "cherry picked from" msg
395 test_expect_success '--continue respects -x in first commit in multi-pick' '
396 pristine_detach initial &&
397 test_must_fail git cherry-pick -x picked anotherpick &&
398 echo c >foo &&
399 git add foo &&
400 git cherry-pick --continue &&
401 test_path_is_missing .git/sequencer &&
402 git cat-file commit HEAD^ >msg &&
403 picked=$(git rev-parse --verify picked) &&
404 grep "cherry picked from.*$picked" msg
407 test_expect_failure '--signoff is automatically propagated to resolved conflict' '
408 pristine_detach initial &&
409 test_expect_code 1 git cherry-pick --signoff base..anotherpick &&
410 echo "c" >foo &&
411 git add foo &&
412 git commit &&
413 git cherry-pick --continue &&
414 test_path_is_missing .git/sequencer &&
415 git cat-file commit HEAD >anotherpick_msg &&
416 git cat-file commit HEAD~1 >picked_msg &&
417 git cat-file commit HEAD~2 >unrelatedpick_msg &&
418 git cat-file commit HEAD~3 >initial_msg &&
419 test_must_fail grep "Signed-off-by:" initial_msg &&
420 grep "Signed-off-by:" unrelatedpick_msg &&
421 test_must_fail grep "Signed-off-by:" picked_msg &&
422 grep "Signed-off-by:" anotherpick_msg
425 test_expect_failure '--signoff dropped for implicit commit of resolution, multi-pick case' '
426 pristine_detach initial &&
427 test_must_fail git cherry-pick -s picked anotherpick &&
428 echo c >foo &&
429 git add foo &&
430 git cherry-pick --continue &&
432 git diff --exit-code HEAD &&
433 test_cmp_rev initial HEAD^^ &&
434 git cat-file commit HEAD^ >msg &&
435 ! grep Signed-off-by: msg
438 test_expect_failure 'sign-off needs to be reaffirmed after conflict resolution, single-pick case' '
439 pristine_detach initial &&
440 test_must_fail git cherry-pick -s picked &&
441 echo c >foo &&
442 git add foo &&
443 git cherry-pick --continue &&
445 git diff --exit-code HEAD &&
446 test_cmp_rev initial HEAD^ &&
447 git cat-file commit HEAD >msg &&
448 ! grep Signed-off-by: msg
451 test_expect_success 'malformed instruction sheet 1' '
452 pristine_detach initial &&
453 test_expect_code 1 git cherry-pick base..anotherpick &&
454 echo "resolved" >foo &&
455 git add foo &&
456 git commit &&
457 sed "s/pick /pick/" .git/sequencer/todo >new_sheet &&
458 cp new_sheet .git/sequencer/todo &&
459 test_expect_code 128 git cherry-pick --continue
462 test_expect_success 'malformed instruction sheet 2' '
463 pristine_detach initial &&
464 test_expect_code 1 git cherry-pick base..anotherpick &&
465 echo "resolved" >foo &&
466 git add foo &&
467 git commit &&
468 sed "s/pick/revert/" .git/sequencer/todo >new_sheet &&
469 cp new_sheet .git/sequencer/todo &&
470 test_expect_code 128 git cherry-pick --continue
473 test_expect_success 'empty commit set' '
474 pristine_detach initial &&
475 test_expect_code 128 git cherry-pick base..base
478 test_expect_success 'malformed instruction sheet 3' '
479 pristine_detach initial &&
480 test_expect_code 1 git cherry-pick base..anotherpick &&
481 echo "resolved" >foo &&
482 git add foo &&
483 git commit &&
484 sed "s/pick \([0-9a-f]*\)/pick $_r10/" .git/sequencer/todo >new_sheet &&
485 cp new_sheet .git/sequencer/todo &&
486 test_expect_code 128 git cherry-pick --continue
489 test_expect_success 'instruction sheet, fat-fingers version' '
490 pristine_detach initial &&
491 test_expect_code 1 git cherry-pick base..anotherpick &&
492 echo "c" >foo &&
493 git add foo &&
494 git commit &&
495 sed "s/pick \([0-9a-f]*\)/pick \1 /" .git/sequencer/todo >new_sheet &&
496 cp new_sheet .git/sequencer/todo &&
497 git cherry-pick --continue
500 test_expect_success 'commit descriptions in insn sheet are optional' '
501 pristine_detach initial &&
502 test_expect_code 1 git cherry-pick base..anotherpick &&
503 echo "c" >foo &&
504 git add foo &&
505 git commit &&
506 cut -d" " -f1,2 .git/sequencer/todo >new_sheet &&
507 cp new_sheet .git/sequencer/todo &&
508 git cherry-pick --continue &&
509 test_path_is_missing .git/sequencer &&
510 git rev-list HEAD >commits &&
511 test_line_count = 4 commits
514 test_done