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
17 # Repeat first match 10 times
18 _r10='\1\1\1\1\1\1\1\1\1\1'
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 &&
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 # to make sure that the session to cherry-pick a sequence
65 # gets interrupted, use a high-enough number that is larger
66 # than the number of parents of any commit we have created
68 test_expect_code 128 git cherry-pick -s -m $mainline --strategy=recursive -X patience -X ours initial..anotherpick &&
69 test_path_is_dir .git/sequencer &&
70 test_path_is_file .git/sequencer/head &&
71 test_path_is_file .git/sequencer/todo &&
72 test_path_is_file .git/sequencer/opts &&
73 echo "true" >expect &&
74 git config --file=.git/sequencer/opts --get-all options.signoff >actual &&
75 test_cmp expect actual &&
76 echo "$mainline" >expect &&
77 git config --file=.git/sequencer/opts --get-all options.mainline >actual &&
78 test_cmp expect actual &&
79 echo "recursive" >expect &&
80 git config --file=.git/sequencer/opts --get-all options.strategy >actual &&
81 test_cmp expect actual &&
82 cat >expect <<-\EOF &&
86 git config --file=.git/sequencer/opts --get-all options.strategy-option >actual &&
87 test_cmp expect actual
90 test_expect_success 'cherry-pick cleans up sequencer state upon success' '
91 pristine_detach initial &&
92 git cherry-pick initial..picked &&
93 test_path_is_missing .git/sequencer
96 test_expect_success '--quit does not complain when no cherry-pick is in progress' '
97 pristine_detach initial &&
98 git cherry-pick --quit
101 test_expect_success '--abort requires cherry-pick in progress' '
102 pristine_detach initial &&
103 test_must_fail git cherry-pick --abort
106 test_expect_success '--quit cleans up sequencer state' '
107 pristine_detach initial &&
108 test_expect_code 1 git cherry-pick base..picked &&
109 git cherry-pick --quit &&
110 test_path_is_missing .git/sequencer &&
111 test_path_is_missing .git/CHERRY_PICK_HEAD
114 test_expect_success '--quit keeps HEAD and conflicted index intact' '
115 pristine_detach initial &&
116 cat >expect <<-\EOF &&
118 :100644 100644 OBJID OBJID M unrelated
120 :000000 100644 OBJID OBJID A foo
121 :000000 100644 OBJID OBJID A unrelated
123 test_expect_code 1 git cherry-pick base..picked &&
124 git cherry-pick --quit &&
125 test_path_is_missing .git/sequencer &&
126 test_must_fail git update-index --refresh &&
129 git diff-tree --root --stdin |
130 sed "s/$OID_REGEX/OBJID/g"
132 test_cmp expect actual
135 test_expect_success '--abort to cancel multiple cherry-pick' '
136 pristine_detach initial &&
137 test_expect_code 1 git cherry-pick base..anotherpick &&
138 git cherry-pick --abort &&
139 test_path_is_missing .git/sequencer &&
140 test_path_is_missing .git/CHERRY_PICK_HEAD &&
141 test_cmp_rev initial HEAD &&
142 git update-index --refresh &&
143 git diff-index --exit-code HEAD
146 test_expect_success '--abort to cancel single cherry-pick' '
147 pristine_detach initial &&
148 test_expect_code 1 git cherry-pick picked &&
149 git cherry-pick --abort &&
150 test_path_is_missing .git/sequencer &&
151 test_path_is_missing .git/CHERRY_PICK_HEAD &&
152 test_cmp_rev initial HEAD &&
153 git update-index --refresh &&
154 git diff-index --exit-code HEAD
157 test_expect_success '--abort does not unsafely change HEAD' '
158 pristine_detach initial &&
159 test_must_fail git cherry-pick picked anotherpick &&
160 git reset --hard base &&
161 test_must_fail git cherry-pick picked anotherpick &&
162 git cherry-pick --abort 2>actual &&
163 test_i18ngrep "You seem to have moved HEAD" actual &&
164 test_cmp_rev base HEAD
167 test_expect_success 'cherry-pick --abort to cancel multiple revert' '
168 pristine_detach anotherpick &&
169 test_expect_code 1 git revert base..picked &&
170 git cherry-pick --abort &&
171 test_path_is_missing .git/sequencer &&
172 test_path_is_missing .git/CHERRY_PICK_HEAD &&
173 test_cmp_rev anotherpick HEAD &&
174 git update-index --refresh &&
175 git diff-index --exit-code HEAD
178 test_expect_success 'revert --abort works, too' '
179 pristine_detach anotherpick &&
180 test_expect_code 1 git revert base..picked &&
181 git revert --abort &&
182 test_path_is_missing .git/sequencer &&
183 test_cmp_rev anotherpick HEAD
186 test_expect_success '--abort to cancel single revert' '
187 pristine_detach anotherpick &&
188 test_expect_code 1 git revert picked &&
189 git revert --abort &&
190 test_path_is_missing .git/sequencer &&
191 test_cmp_rev anotherpick HEAD &&
192 git update-index --refresh &&
193 git diff-index --exit-code HEAD
196 test_expect_success '--abort keeps unrelated change, easy case' '
197 pristine_detach unrelatedpick &&
198 echo changed >expect &&
199 test_expect_code 1 git cherry-pick picked..yetanotherpick &&
200 echo changed >unrelated &&
201 git cherry-pick --abort &&
202 test_cmp expect unrelated
205 test_expect_success '--abort refuses to clobber unrelated change, harder case' '
206 pristine_detach initial &&
207 echo changed >expect &&
208 test_expect_code 1 git cherry-pick base..anotherpick &&
209 echo changed >unrelated &&
210 test_must_fail git cherry-pick --abort &&
211 test_cmp expect unrelated &&
212 git rev-list HEAD >log &&
213 test_line_count = 2 log &&
214 test_must_fail git update-index --refresh &&
216 git checkout unrelated &&
217 git cherry-pick --abort &&
218 test_cmp_rev initial HEAD
221 test_expect_success 'cherry-pick still writes sequencer state when one commit is left' '
222 pristine_detach initial &&
223 test_expect_code 1 git cherry-pick base..picked &&
224 test_path_is_dir .git/sequencer &&
225 echo "resolved" >foo &&
230 git diff-tree --root --stdin |
231 sed "s/$OID_REGEX/OBJID/g"
233 cat >expect <<-\EOF &&
235 :100644 100644 OBJID OBJID M foo
237 :100644 100644 OBJID OBJID M unrelated
239 :000000 100644 OBJID OBJID A foo
240 :000000 100644 OBJID OBJID A unrelated
242 test_cmp expect actual
245 test_expect_success '--abort after last commit in sequence' '
246 pristine_detach initial &&
247 test_expect_code 1 git cherry-pick base..picked &&
248 git cherry-pick --abort &&
249 test_path_is_missing .git/sequencer &&
250 test_path_is_missing .git/CHERRY_PICK_HEAD &&
251 test_cmp_rev initial HEAD &&
252 git update-index --refresh &&
253 git diff-index --exit-code HEAD
256 test_expect_success 'cherry-pick does not implicitly stomp an existing operation' '
257 pristine_detach initial &&
258 test_expect_code 1 git cherry-pick base..anotherpick &&
259 test-tool chmtime --get .git/sequencer >expect &&
260 test_expect_code 128 git cherry-pick unrelatedpick &&
261 test-tool chmtime --get .git/sequencer >actual &&
262 test_cmp expect actual
265 test_expect_success '--continue complains when no cherry-pick is in progress' '
266 pristine_detach initial &&
267 test_expect_code 128 git cherry-pick --continue
270 test_expect_success '--continue complains when there are unresolved conflicts' '
271 pristine_detach initial &&
272 test_expect_code 1 git cherry-pick base..anotherpick &&
273 test_expect_code 128 git cherry-pick --continue
276 test_expect_success '--continue of single cherry-pick' '
277 pristine_detach initial &&
279 test_must_fail git cherry-pick picked &&
282 git cherry-pick --continue &&
284 test_cmp expect foo &&
285 test_cmp_rev initial HEAD^ &&
286 git diff --exit-code HEAD &&
287 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
290 test_expect_success '--continue of single revert' '
291 pristine_detach initial &&
292 echo resolved >expect &&
293 echo "Revert \"picked\"" >expect.msg &&
294 test_must_fail git revert picked &&
295 echo resolved >foo &&
297 git cherry-pick --continue &&
299 git diff --exit-code HEAD &&
300 test_cmp expect foo &&
301 test_cmp_rev initial HEAD^ &&
302 git diff-tree -s --pretty=tformat:%s HEAD >msg &&
303 test_cmp expect.msg msg &&
304 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
305 test_must_fail git rev-parse --verify REVERT_HEAD
308 test_expect_success '--continue after resolving conflicts' '
309 pristine_detach initial &&
311 cat >expect.log <<-\EOF &&
313 :100644 100644 OBJID OBJID M foo
315 :100644 100644 OBJID OBJID M foo
317 :100644 100644 OBJID OBJID M unrelated
319 :000000 100644 OBJID OBJID A foo
320 :000000 100644 OBJID OBJID A unrelated
322 test_must_fail git cherry-pick base..anotherpick &&
325 git cherry-pick --continue &&
328 git diff-tree --root --stdin |
329 sed "s/$OID_REGEX/OBJID/g"
331 test_cmp expect foo &&
332 test_cmp expect.log actual.log
335 test_expect_success '--continue after resolving conflicts and committing' '
336 pristine_detach initial &&
337 test_expect_code 1 git cherry-pick base..anotherpick &&
341 git cherry-pick --continue &&
342 test_path_is_missing .git/sequencer &&
345 git diff-tree --root --stdin |
346 sed "s/$OID_REGEX/OBJID/g"
348 cat >expect <<-\EOF &&
350 :100644 100644 OBJID OBJID M foo
352 :100644 100644 OBJID OBJID M foo
354 :100644 100644 OBJID OBJID M unrelated
356 :000000 100644 OBJID OBJID A foo
357 :000000 100644 OBJID OBJID A unrelated
359 test_cmp expect actual
362 test_expect_success '--continue asks for help after resolving patch to nil' '
363 pristine_detach conflicting &&
364 test_must_fail git cherry-pick initial..picked &&
366 test_cmp_rev unrelatedpick CHERRY_PICK_HEAD &&
367 git checkout HEAD -- unrelated &&
368 test_must_fail git cherry-pick --continue 2>msg &&
369 test_i18ngrep "The previous cherry-pick is now empty" msg
372 test_expect_success 'follow advice and skip nil patch' '
373 pristine_detach conflicting &&
374 test_must_fail git cherry-pick initial..picked &&
376 git checkout HEAD -- unrelated &&
377 test_must_fail git cherry-pick --continue &&
379 git cherry-pick --continue &&
381 git rev-list initial..HEAD >commits &&
382 test_line_count = 3 commits
385 test_expect_success '--continue respects opts' '
386 pristine_detach initial &&
387 test_expect_code 1 git cherry-pick -x base..anotherpick &&
391 git cherry-pick --continue &&
392 test_path_is_missing .git/sequencer &&
393 git cat-file commit HEAD >anotherpick_msg &&
394 git cat-file commit HEAD~1 >picked_msg &&
395 git cat-file commit HEAD~2 >unrelatedpick_msg &&
396 git cat-file commit HEAD~3 >initial_msg &&
397 ! grep "cherry picked from" initial_msg &&
398 grep "cherry picked from" unrelatedpick_msg &&
399 grep "cherry picked from" picked_msg &&
400 grep "cherry picked from" anotherpick_msg
403 test_expect_success '--continue of single-pick respects -x' '
404 pristine_detach initial &&
405 test_must_fail git cherry-pick -x picked &&
408 git cherry-pick --continue &&
409 test_path_is_missing .git/sequencer &&
410 git cat-file commit HEAD >msg &&
411 grep "cherry picked from" msg
414 test_expect_success '--continue respects -x in first commit in multi-pick' '
415 pristine_detach initial &&
416 test_must_fail git cherry-pick -x picked anotherpick &&
419 git cherry-pick --continue &&
420 test_path_is_missing .git/sequencer &&
421 git cat-file commit HEAD^ >msg &&
422 picked=$(git rev-parse --verify picked) &&
423 grep "cherry picked from.*$picked" msg
426 test_expect_failure '--signoff is automatically propagated to resolved conflict' '
427 pristine_detach initial &&
428 test_expect_code 1 git cherry-pick --signoff base..anotherpick &&
432 git cherry-pick --continue &&
433 test_path_is_missing .git/sequencer &&
434 git cat-file commit HEAD >anotherpick_msg &&
435 git cat-file commit HEAD~1 >picked_msg &&
436 git cat-file commit HEAD~2 >unrelatedpick_msg &&
437 git cat-file commit HEAD~3 >initial_msg &&
438 ! grep "Signed-off-by:" initial_msg &&
439 grep "Signed-off-by:" unrelatedpick_msg &&
440 ! grep "Signed-off-by:" picked_msg &&
441 grep "Signed-off-by:" anotherpick_msg
444 test_expect_failure '--signoff dropped for implicit commit of resolution, multi-pick case' '
445 pristine_detach initial &&
446 test_must_fail git cherry-pick -s picked anotherpick &&
449 git cherry-pick --continue &&
451 git diff --exit-code HEAD &&
452 test_cmp_rev initial HEAD^^ &&
453 git cat-file commit HEAD^ >msg &&
454 ! grep Signed-off-by: msg
457 test_expect_failure 'sign-off needs to be reaffirmed after conflict resolution, single-pick case' '
458 pristine_detach initial &&
459 test_must_fail git cherry-pick -s picked &&
462 git cherry-pick --continue &&
464 git diff --exit-code HEAD &&
465 test_cmp_rev initial HEAD^ &&
466 git cat-file commit HEAD >msg &&
467 ! grep Signed-off-by: msg
470 test_expect_success 'malformed instruction sheet 1' '
471 pristine_detach initial &&
472 test_expect_code 1 git cherry-pick base..anotherpick &&
473 echo "resolved" >foo &&
476 sed "s/pick /pick/" .git/sequencer/todo >new_sheet &&
477 cp new_sheet .git/sequencer/todo &&
478 test_expect_code 128 git cherry-pick --continue
481 test_expect_success 'malformed instruction sheet 2' '
482 pristine_detach initial &&
483 test_expect_code 1 git cherry-pick base..anotherpick &&
484 echo "resolved" >foo &&
487 sed "s/pick/revert/" .git/sequencer/todo >new_sheet &&
488 cp new_sheet .git/sequencer/todo &&
489 test_expect_code 128 git cherry-pick --continue
492 test_expect_success 'empty commit set (no commits to walk)' '
493 pristine_detach initial &&
494 test_expect_code 128 git cherry-pick base..base
497 test_expect_success 'empty commit set (culled during walk)' '
498 pristine_detach initial &&
499 test_expect_code 128 git cherry-pick -2 --author=no.such.author base
502 test_expect_success 'malformed instruction sheet 3' '
503 pristine_detach initial &&
504 test_expect_code 1 git cherry-pick base..anotherpick &&
505 echo "resolved" >foo &&
508 sed "s/pick \([0-9a-f]*\)/pick $_r10/" .git/sequencer/todo >new_sheet &&
509 cp new_sheet .git/sequencer/todo &&
510 test_expect_code 128 git cherry-pick --continue
513 test_expect_success 'instruction sheet, fat-fingers version' '
514 pristine_detach initial &&
515 test_expect_code 1 git cherry-pick base..anotherpick &&
519 sed "s/pick \([0-9a-f]*\)/pick \1 /" .git/sequencer/todo >new_sheet &&
520 cp new_sheet .git/sequencer/todo &&
521 git cherry-pick --continue
524 test_expect_success 'commit descriptions in insn sheet are optional' '
525 pristine_detach initial &&
526 test_expect_code 1 git cherry-pick base..anotherpick &&
530 cut -d" " -f1,2 .git/sequencer/todo >new_sheet &&
531 cp new_sheet .git/sequencer/todo &&
532 git cherry-pick --continue &&
533 test_path_is_missing .git/sequencer &&
534 git rev-list HEAD >commits &&
535 test_line_count = 4 commits