3 test_description
='test cherry-pick and revert with conflicts
6 + picked: rewrites foo to c
7 + base: rewrites foo to b
8 + initial: writes foo as a, unrelated as unrelated
12 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
=main
13 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
15 TEST_CREATE_REPO_NO_TEMPLATE
=1
16 TEST_PASSES_SANITIZE_LEAK
=true
20 git checkout
-f "$1^0" &&
21 git read-tree
-u --reset HEAD
&&
22 git clean
-d -f -f -q -x
25 test_expect_success setup
'
27 echo unrelated >unrelated &&
29 test_commit initial foo a &&
30 test_commit base foo b &&
31 test_commit picked foo c &&
32 test_commit --signoff picked-signed foo d &&
33 git checkout -b topic initial &&
34 test_commit redundant-pick foo c redundant &&
35 git commit --allow-empty --allow-empty-message &&
38 git config advice.detachedhead false
42 test_expect_success
'failed cherry-pick does not advance HEAD' '
43 pristine_detach initial &&
45 head=$(git rev-parse HEAD) &&
46 test_must_fail git cherry-pick picked &&
47 newhead=$(git rev-parse HEAD) &&
49 test "$head" = "$newhead"
52 test_expect_success
'advice from failed cherry-pick' '
53 pristine_detach initial &&
55 picked=$(git rev-parse --short picked) &&
56 cat <<-EOF >expected &&
57 error: could not apply $picked... picked
58 hint: After resolving the conflicts, mark them with
59 hint: "git add/rm <pathspec>", then run
60 hint: "git cherry-pick --continue".
61 hint: You can instead skip this commit with "git cherry-pick --skip".
62 hint: To abort and get back to the state before "git cherry-pick",
63 hint: run "git cherry-pick --abort".
64 hint: Disable this message with "git config advice.mergeConflict false"
66 test_must_fail git cherry-pick picked 2>actual &&
68 test_cmp expected actual
71 test_expect_success
'advice from failed cherry-pick --no-commit' "
72 pristine_detach initial &&
74 picked=\$(git rev-parse --short picked) &&
75 cat <<-EOF >expected &&
76 error: could not apply \$picked... picked
77 hint: after resolving the conflicts, mark the corrected paths
78 hint: with 'git add <paths>' or 'git rm <paths>'
79 hint: Disable this message with \"git config advice.mergeConflict false\"
81 test_must_fail git cherry-pick --no-commit picked 2>actual &&
83 test_cmp expected actual
86 test_expect_success
'failed cherry-pick sets CHERRY_PICK_HEAD' '
87 pristine_detach initial &&
88 test_must_fail git cherry-pick picked &&
89 test_cmp_rev picked CHERRY_PICK_HEAD
92 test_expect_success
'successful cherry-pick does not set CHERRY_PICK_HEAD' '
93 pristine_detach initial &&
94 git cherry-pick base &&
95 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
98 test_expect_success
'cherry-pick --no-commit does not set CHERRY_PICK_HEAD' '
99 pristine_detach initial &&
100 git cherry-pick --no-commit base &&
101 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
104 test_expect_success
'cherry-pick w/dirty tree does not set CHERRY_PICK_HEAD' '
105 pristine_detach initial &&
107 test_must_fail git cherry-pick base &&
108 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
111 test_expect_success \
112 'cherry-pick --strategy=resolve w/dirty tree does not set CHERRY_PICK_HEAD' '
113 pristine_detach initial &&
115 test_must_fail git cherry-pick --strategy=resolve base &&
116 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
119 test_expect_success
'GIT_CHERRY_PICK_HELP suppresses CHERRY_PICK_HEAD' '
120 pristine_detach initial &&
122 GIT_CHERRY_PICK_HELP="and then do something else" &&
123 export GIT_CHERRY_PICK_HELP &&
124 test_must_fail git cherry-pick picked
126 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
129 test_expect_success
'git reset clears CHERRY_PICK_HEAD' '
130 pristine_detach initial &&
132 test_must_fail git cherry-pick picked &&
135 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
138 test_expect_success
'failed commit does not clear CHERRY_PICK_HEAD' '
139 pristine_detach initial &&
141 test_must_fail git cherry-pick picked &&
142 test_must_fail git commit &&
144 test_cmp_rev picked CHERRY_PICK_HEAD
147 test_expect_success
'cancelled commit does not clear CHERRY_PICK_HEAD' '
148 pristine_detach initial &&
150 test_must_fail git cherry-pick picked &&
151 echo resolved >foo &&
153 git update-index --refresh -q &&
154 test_must_fail git diff-index --exit-code HEAD &&
158 test_must_fail git commit
161 test_cmp_rev picked CHERRY_PICK_HEAD
164 test_expect_success
'successful commit clears CHERRY_PICK_HEAD' '
165 pristine_detach initial &&
167 test_must_fail git cherry-pick picked &&
168 echo resolved >foo &&
172 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
175 test_expect_success
'partial commit of cherry-pick fails' '
176 pristine_detach initial &&
178 test_must_fail git cherry-pick picked &&
179 echo resolved >foo &&
181 test_must_fail git commit foo 2>err &&
183 test_grep "cannot do a partial commit during a cherry-pick." err
186 test_expect_success
'commit --amend of cherry-pick fails' '
187 pristine_detach initial &&
189 test_must_fail git cherry-pick picked &&
190 echo resolved >foo &&
192 test_must_fail git commit --amend 2>err &&
194 test_grep "in the middle of a cherry-pick -- cannot amend." err
197 test_expect_success
'successful final commit clears cherry-pick state' '
198 pristine_detach initial &&
200 test_must_fail git cherry-pick base picked-signed &&
201 echo resolved >foo &&
202 test_path_is_file .git/sequencer/todo &&
204 test_path_is_missing .git/sequencer
207 test_expect_success
'reset after final pick clears cherry-pick state' '
208 pristine_detach initial &&
210 test_must_fail git cherry-pick base picked-signed &&
211 echo resolved >foo &&
212 test_path_is_file .git/sequencer/todo &&
214 test_path_is_missing .git/sequencer
217 test_expect_success
'failed cherry-pick produces dirty index' '
218 pristine_detach initial &&
220 test_must_fail git cherry-pick picked &&
222 test_must_fail git update-index --refresh -q &&
223 test_must_fail git diff-index --exit-code HEAD
226 test_expect_success
'failed cherry-pick registers participants in index' '
227 pristine_detach initial &&
229 git checkout base -- foo &&
230 git ls-files --stage foo &&
231 git checkout initial -- foo &&
232 git ls-files --stage foo &&
233 git checkout picked -- foo &&
234 git ls-files --stage foo
240 " stages >expected &&
241 git read-tree -u --reset HEAD &&
243 test_must_fail git cherry-pick picked &&
244 git ls-files --stage --unmerged >actual &&
246 test_cmp expected actual
249 test_expect_success \
250 'cherry-pick conflict, ensure commit.cleanup = scissors places scissors line properly' '
251 pristine_detach initial &&
252 git config commit.cleanup scissors &&
253 cat <<-EOF >expected &&
256 # ------------------------ >8 ------------------------
257 # Do not modify or remove the line above.
258 # Everything below it will be ignored.
264 test_must_fail git cherry-pick picked &&
266 test_cmp expected .git/MERGE_MSG
269 test_expect_success \
270 'cherry-pick conflict, ensure cleanup=scissors places scissors line properly' '
271 pristine_detach initial &&
272 git config --unset commit.cleanup &&
273 cat <<-EOF >expected &&
276 # ------------------------ >8 ------------------------
277 # Do not modify or remove the line above.
278 # Everything below it will be ignored.
284 test_must_fail git cherry-pick --cleanup=scissors picked &&
286 test_cmp expected .git/MERGE_MSG
289 test_expect_success
'failed cherry-pick describes conflict in work tree' '
290 pristine_detach initial &&
291 cat <<-EOF >expected &&
296 >>>>>>> objid (picked)
299 test_must_fail git cherry-pick picked &&
301 sed "s/[a-f0-9]* (/objid (/" foo >actual &&
302 test_cmp expected actual
305 test_expect_success
'diff3 -m style' '
306 pristine_detach initial &&
307 git config merge.conflictstyle diff3 &&
308 cat <<-EOF >expected &&
311 ||||||| parent of objid (picked)
315 >>>>>>> objid (picked)
318 test_must_fail git cherry-pick picked &&
320 sed "s/[a-f0-9]* (/objid (/" foo >actual &&
321 test_cmp expected actual
324 test_expect_success
'revert also handles conflicts sanely' '
325 git config --unset merge.conflictstyle &&
326 pristine_detach initial &&
327 cat <<-EOF >expected &&
332 >>>>>>> parent of objid (picked)
335 git checkout picked -- foo &&
336 git ls-files --stage foo &&
337 git checkout initial -- foo &&
338 git ls-files --stage foo &&
339 git checkout base -- foo &&
340 git ls-files --stage foo
346 " stages >expected-stages &&
347 git read-tree -u --reset HEAD &&
349 head=$(git rev-parse HEAD) &&
350 test_must_fail git revert picked &&
351 newhead=$(git rev-parse HEAD) &&
352 git ls-files --stage --unmerged >actual-stages &&
354 test "$head" = "$newhead" &&
355 test_must_fail git update-index --refresh -q &&
356 test_must_fail git diff-index --exit-code HEAD &&
357 test_cmp expected-stages actual-stages &&
358 sed "s/[a-f0-9]* (/objid (/" foo >actual &&
359 test_cmp expected actual
362 test_expect_success
'failed revert sets REVERT_HEAD' '
363 pristine_detach initial &&
364 test_must_fail git revert picked &&
365 test_cmp_rev picked REVERT_HEAD
368 test_expect_success
'successful revert does not set REVERT_HEAD' '
369 pristine_detach base &&
371 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
372 test_must_fail git rev-parse --verify REVERT_HEAD
375 test_expect_success
'revert --no-commit sets REVERT_HEAD' '
376 pristine_detach base &&
377 git revert --no-commit base &&
378 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
379 test_cmp_rev base REVERT_HEAD
382 test_expect_success
'revert w/dirty tree does not set REVERT_HEAD' '
383 pristine_detach base &&
385 test_must_fail git revert base &&
386 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
387 test_must_fail git rev-parse --verify REVERT_HEAD
390 test_expect_success
'GIT_CHERRY_PICK_HELP does not suppress REVERT_HEAD' '
391 pristine_detach initial &&
393 GIT_CHERRY_PICK_HELP="and then do something else" &&
394 GIT_REVERT_HELP="and then do something else, again" &&
395 export GIT_CHERRY_PICK_HELP GIT_REVERT_HELP &&
396 test_must_fail git revert picked
398 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
399 test_cmp_rev picked REVERT_HEAD
402 test_expect_success
'git reset clears REVERT_HEAD' '
403 pristine_detach initial &&
404 test_must_fail git revert picked &&
406 test_must_fail git rev-parse --verify REVERT_HEAD
409 test_expect_success
'failed commit does not clear REVERT_HEAD' '
410 pristine_detach initial &&
411 test_must_fail git revert picked &&
412 test_must_fail git commit &&
413 test_cmp_rev picked REVERT_HEAD
416 test_expect_success
'successful final commit clears revert state' '
417 pristine_detach picked-signed &&
419 test_must_fail git revert picked-signed base &&
420 echo resolved >foo &&
421 test_path_is_file .git/sequencer/todo &&
423 test_path_is_missing .git/sequencer
426 test_expect_success
'reset after final pick clears revert state' '
427 pristine_detach picked-signed &&
429 test_must_fail git revert picked-signed base &&
430 echo resolved >foo &&
431 test_path_is_file .git/sequencer/todo &&
433 test_path_is_missing .git/sequencer
436 test_expect_success
'revert conflict, diff3 -m style' '
437 pristine_detach initial &&
438 git config merge.conflictstyle diff3 &&
439 cat <<-EOF >expected &&
442 ||||||| objid (picked)
446 >>>>>>> parent of objid (picked)
449 test_must_fail git revert picked &&
451 sed "s/[a-f0-9]* (/objid (/" foo >actual &&
452 test_cmp expected actual
455 test_expect_success \
456 'revert conflict, ensure commit.cleanup = scissors places scissors line properly' '
457 pristine_detach initial &&
458 git config commit.cleanup scissors &&
459 cat >expected <<-EOF &&
462 This reverts commit OBJID.
464 # ------------------------ >8 ------------------------
465 # Do not modify or remove the line above.
466 # Everything below it will be ignored.
472 test_must_fail git revert picked &&
474 sed "s/$OID_REGEX/OBJID/" .git/MERGE_MSG >actual &&
475 test_cmp expected actual
478 test_expect_success \
479 'revert conflict, ensure cleanup=scissors places scissors line properly' '
480 pristine_detach initial &&
481 git config --unset commit.cleanup &&
482 cat >expected <<-EOF &&
485 This reverts commit OBJID.
487 # ------------------------ >8 ------------------------
488 # Do not modify or remove the line above.
489 # Everything below it will be ignored.
495 test_must_fail git revert --cleanup=scissors picked &&
497 sed "s/$OID_REGEX/OBJID/" .git/MERGE_MSG >actual &&
498 test_cmp expected actual
501 test_expect_success
'failed cherry-pick does not forget -s' '
502 pristine_detach initial &&
503 test_must_fail git cherry-pick -s picked &&
504 test_grep -e "Signed-off-by" .git/MERGE_MSG
507 test_expect_success
'commit after failed cherry-pick does not add duplicated -s' '
508 pristine_detach initial &&
509 test_must_fail git cherry-pick -s picked-signed &&
511 test $(git show -s >tmp && grep -c "Signed-off-by" tmp && rm tmp) = 1
514 test_expect_success
'commit after failed cherry-pick adds -s at the right place' '
515 pristine_detach initial &&
516 test_must_fail git cherry-pick picked &&
520 # Do S-o-b and Conflicts appear in the right order?
521 cat <<-\EOF >expect &&
522 Signed-off-by: C O Mitter <committer@example.com>
525 grep -e "^# Conflicts:" -e "^Signed-off-by" .git/COMMIT_EDITMSG >actual &&
526 test_cmp expect actual &&
528 cat <<-\EOF >expected &&
531 Signed-off-by: C O Mitter <committer@example.com>
534 git show -s --pretty=format:%B >actual &&
535 test_cmp expected actual
538 test_expect_success
'commit --amend -s places the sign-off at the right place' '
539 pristine_detach initial &&
540 test_must_fail git cherry-pick picked &&
542 # emulate old-style conflicts block
543 mv .git/MERGE_MSG .git/MERGE_MSG+ &&
544 sed -e "/^# Conflicts:/,\$s/^# *//" .git/MERGE_MSG+ >.git/MERGE_MSG &&
547 git commit --amend -s &&
549 # Do S-o-b and Conflicts appear in the right order?
550 cat <<-\EOF >expect &&
551 Signed-off-by: C O Mitter <committer@example.com>
554 grep -e "^Conflicts:" -e "^Signed-off-by" .git/COMMIT_EDITMSG >actual &&
555 test_cmp expect actual
558 test_expect_success
'cherry-pick preserves sparse-checkout' '
559 pristine_detach initial &&
560 test_config core.sparseCheckout true &&
562 echo \"/*\" >.git/info/sparse-checkout
563 git read-tree --reset -u HEAD
564 rm .git/info/sparse-checkout" &&
566 echo /unrelated >.git/info/sparse-checkout &&
567 git read-tree --reset -u HEAD &&
568 test_must_fail git cherry-pick -Xours picked>actual &&
569 test_grep ! "Changes not staged for commit:" actual
572 test_expect_success
'cherry-pick --continue remembers --keep-redundant-commits' '
573 test_when_finished "git cherry-pick --abort || :" &&
574 pristine_detach initial &&
575 test_must_fail git cherry-pick --keep-redundant-commits picked redundant &&
578 git cherry-pick --continue
581 test_expect_success
'cherry-pick --continue remembers --allow-empty and --allow-empty-message' '
582 test_when_finished "git cherry-pick --abort || :" &&
583 pristine_detach initial &&
584 test_must_fail git cherry-pick --allow-empty --allow-empty-message \
588 git cherry-pick --continue