]> git.ipfire.org Git - thirdparty/git.git/blob - t/t3507-cherry-pick-conflict.sh
014001b8f325c0f1d8b140e7828332bb15610574
[thirdparty/git.git] / t / t3507-cherry-pick-conflict.sh
1 #!/bin/sh
2
3 test_description='test cherry-pick and revert with conflicts
4
5 -
6 + picked: rewrites foo to c
7 + base: rewrites foo to b
8 + initial: writes foo as a, unrelated as unrelated
9
10 '
11
12 GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
13 export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
14
15 . ./test-lib.sh
16
17 pristine_detach () {
18 git checkout -f "$1^0" &&
19 git read-tree -u --reset HEAD &&
20 git clean -d -f -f -q -x
21 }
22
23 test_expect_success setup '
24
25 echo unrelated >unrelated &&
26 git add unrelated &&
27 test_commit initial foo a &&
28 test_commit base foo b &&
29 test_commit picked foo c &&
30 test_commit --signoff picked-signed foo d &&
31 git checkout -b topic initial &&
32 test_commit redundant-pick foo c redundant &&
33 git commit --allow-empty --allow-empty-message &&
34 git tag empty &&
35 git checkout main &&
36 git config advice.detachedhead false
37
38 '
39
40 test_expect_success 'failed cherry-pick does not advance HEAD' '
41 pristine_detach initial &&
42
43 head=$(git rev-parse HEAD) &&
44 test_must_fail git cherry-pick picked &&
45 newhead=$(git rev-parse HEAD) &&
46
47 test "$head" = "$newhead"
48 '
49
50 test_expect_success 'advice from failed cherry-pick' "
51 pristine_detach initial &&
52
53 picked=\$(git rev-parse --short picked) &&
54 cat <<-EOF >expected &&
55 error: could not apply \$picked... picked
56 hint: after resolving the conflicts, mark the corrected paths
57 hint: with 'git add <paths>' or 'git rm <paths>'
58 hint: and commit the result with 'git commit'
59 EOF
60 test_must_fail git cherry-pick picked 2>actual &&
61
62 test_cmp expected actual
63 "
64
65 test_expect_success 'advice from failed cherry-pick --no-commit' "
66 pristine_detach initial &&
67
68 picked=\$(git rev-parse --short picked) &&
69 cat <<-EOF >expected &&
70 error: could not apply \$picked... picked
71 hint: after resolving the conflicts, mark the corrected paths
72 hint: with 'git add <paths>' or 'git rm <paths>'
73 EOF
74 test_must_fail git cherry-pick --no-commit picked 2>actual &&
75
76 test_cmp expected actual
77 "
78
79 test_expect_success 'failed cherry-pick sets CHERRY_PICK_HEAD' '
80 pristine_detach initial &&
81 test_must_fail git cherry-pick picked &&
82 test_cmp_rev picked CHERRY_PICK_HEAD
83 '
84
85 test_expect_success 'successful cherry-pick does not set CHERRY_PICK_HEAD' '
86 pristine_detach initial &&
87 git cherry-pick base &&
88 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
89 '
90
91 test_expect_success 'cherry-pick --no-commit does not set CHERRY_PICK_HEAD' '
92 pristine_detach initial &&
93 git cherry-pick --no-commit base &&
94 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
95 '
96
97 test_expect_success 'cherry-pick w/dirty tree does not set CHERRY_PICK_HEAD' '
98 pristine_detach initial &&
99 echo foo >foo &&
100 test_must_fail git cherry-pick base &&
101 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
102 '
103
104 test_expect_success \
105 'cherry-pick --strategy=resolve w/dirty tree does not set CHERRY_PICK_HEAD' '
106 pristine_detach initial &&
107 echo foo >foo &&
108 test_must_fail git cherry-pick --strategy=resolve base &&
109 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
110 '
111
112 test_expect_success 'GIT_CHERRY_PICK_HELP suppresses CHERRY_PICK_HEAD' '
113 pristine_detach initial &&
114 (
115 GIT_CHERRY_PICK_HELP="and then do something else" &&
116 export GIT_CHERRY_PICK_HELP &&
117 test_must_fail git cherry-pick picked
118 ) &&
119 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
120 '
121
122 test_expect_success 'git reset clears CHERRY_PICK_HEAD' '
123 pristine_detach initial &&
124
125 test_must_fail git cherry-pick picked &&
126 git reset &&
127
128 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
129 '
130
131 test_expect_success 'failed commit does not clear CHERRY_PICK_HEAD' '
132 pristine_detach initial &&
133
134 test_must_fail git cherry-pick picked &&
135 test_must_fail git commit &&
136
137 test_cmp_rev picked CHERRY_PICK_HEAD
138 '
139
140 test_expect_success 'cancelled commit does not clear CHERRY_PICK_HEAD' '
141 pristine_detach initial &&
142
143 test_must_fail git cherry-pick picked &&
144 echo resolved >foo &&
145 git add foo &&
146 git update-index --refresh -q &&
147 test_must_fail git diff-index --exit-code HEAD &&
148 (
149 GIT_EDITOR=false &&
150 export GIT_EDITOR &&
151 test_must_fail git commit
152 ) &&
153
154 test_cmp_rev picked CHERRY_PICK_HEAD
155 '
156
157 test_expect_success 'successful commit clears CHERRY_PICK_HEAD' '
158 pristine_detach initial &&
159
160 test_must_fail git cherry-pick picked &&
161 echo resolved >foo &&
162 git add foo &&
163 git commit &&
164
165 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD
166 '
167
168 test_expect_success 'partial commit of cherry-pick fails' '
169 pristine_detach initial &&
170
171 test_must_fail git cherry-pick picked &&
172 echo resolved >foo &&
173 git add foo &&
174 test_must_fail git commit foo 2>err &&
175
176 test_i18ngrep "cannot do a partial commit during a cherry-pick." err
177 '
178
179 test_expect_success 'commit --amend of cherry-pick fails' '
180 pristine_detach initial &&
181
182 test_must_fail git cherry-pick picked &&
183 echo resolved >foo &&
184 git add foo &&
185 test_must_fail git commit --amend 2>err &&
186
187 test_i18ngrep "in the middle of a cherry-pick -- cannot amend." err
188 '
189
190 test_expect_success 'successful final commit clears cherry-pick state' '
191 pristine_detach initial &&
192
193 test_must_fail git cherry-pick base picked-signed &&
194 echo resolved >foo &&
195 test_path_is_file .git/sequencer/todo &&
196 git commit -a &&
197 test_path_is_missing .git/sequencer
198 '
199
200 test_expect_success 'reset after final pick clears cherry-pick state' '
201 pristine_detach initial &&
202
203 test_must_fail git cherry-pick base picked-signed &&
204 echo resolved >foo &&
205 test_path_is_file .git/sequencer/todo &&
206 git reset &&
207 test_path_is_missing .git/sequencer
208 '
209
210 test_expect_success 'failed cherry-pick produces dirty index' '
211 pristine_detach initial &&
212
213 test_must_fail git cherry-pick picked &&
214
215 test_must_fail git update-index --refresh -q &&
216 test_must_fail git diff-index --exit-code HEAD
217 '
218
219 test_expect_success 'failed cherry-pick registers participants in index' '
220 pristine_detach initial &&
221 {
222 git checkout base -- foo &&
223 git ls-files --stage foo &&
224 git checkout initial -- foo &&
225 git ls-files --stage foo &&
226 git checkout picked -- foo &&
227 git ls-files --stage foo
228 } >stages &&
229 sed "
230 1 s/ 0 / 1 /
231 2 s/ 0 / 2 /
232 3 s/ 0 / 3 /
233 " stages >expected &&
234 git read-tree -u --reset HEAD &&
235
236 test_must_fail git cherry-pick picked &&
237 git ls-files --stage --unmerged >actual &&
238
239 test_cmp expected actual
240 '
241
242 test_expect_success \
243 'cherry-pick conflict, ensure commit.cleanup = scissors places scissors line properly' '
244 pristine_detach initial &&
245 git config commit.cleanup scissors &&
246 cat <<-EOF >expected &&
247 picked
248
249 # ------------------------ >8 ------------------------
250 # Do not modify or remove the line above.
251 # Everything below it will be ignored.
252 #
253 # Conflicts:
254 # foo
255 EOF
256
257 test_must_fail git cherry-pick picked &&
258
259 test_cmp expected .git/MERGE_MSG
260 '
261
262 test_expect_success \
263 'cherry-pick conflict, ensure cleanup=scissors places scissors line properly' '
264 pristine_detach initial &&
265 git config --unset commit.cleanup &&
266 cat <<-EOF >expected &&
267 picked
268
269 # ------------------------ >8 ------------------------
270 # Do not modify or remove the line above.
271 # Everything below it will be ignored.
272 #
273 # Conflicts:
274 # foo
275 EOF
276
277 test_must_fail git cherry-pick --cleanup=scissors picked &&
278
279 test_cmp expected .git/MERGE_MSG
280 '
281
282 test_expect_success 'failed cherry-pick describes conflict in work tree' '
283 pristine_detach initial &&
284 cat <<-EOF >expected &&
285 <<<<<<< HEAD
286 a
287 =======
288 c
289 >>>>>>> objid (picked)
290 EOF
291
292 test_must_fail git cherry-pick picked &&
293
294 sed "s/[a-f0-9]* (/objid (/" foo >actual &&
295 test_cmp expected actual
296 '
297
298 test_expect_success 'diff3 -m style' '
299 pristine_detach initial &&
300 git config merge.conflictstyle diff3 &&
301 cat <<-EOF >expected &&
302 <<<<<<< HEAD
303 a
304 ||||||| parent of objid (picked)
305 b
306 =======
307 c
308 >>>>>>> objid (picked)
309 EOF
310
311 test_must_fail git cherry-pick picked &&
312
313 sed "s/[a-f0-9]* (/objid (/" foo >actual &&
314 test_cmp expected actual
315 '
316
317 test_expect_success 'revert also handles conflicts sanely' '
318 git config --unset merge.conflictstyle &&
319 pristine_detach initial &&
320 cat <<-EOF >expected &&
321 <<<<<<< HEAD
322 a
323 =======
324 b
325 >>>>>>> parent of objid (picked)
326 EOF
327 {
328 git checkout picked -- foo &&
329 git ls-files --stage foo &&
330 git checkout initial -- foo &&
331 git ls-files --stage foo &&
332 git checkout base -- foo &&
333 git ls-files --stage foo
334 } >stages &&
335 sed "
336 1 s/ 0 / 1 /
337 2 s/ 0 / 2 /
338 3 s/ 0 / 3 /
339 " stages >expected-stages &&
340 git read-tree -u --reset HEAD &&
341
342 head=$(git rev-parse HEAD) &&
343 test_must_fail git revert picked &&
344 newhead=$(git rev-parse HEAD) &&
345 git ls-files --stage --unmerged >actual-stages &&
346
347 test "$head" = "$newhead" &&
348 test_must_fail git update-index --refresh -q &&
349 test_must_fail git diff-index --exit-code HEAD &&
350 test_cmp expected-stages actual-stages &&
351 sed "s/[a-f0-9]* (/objid (/" foo >actual &&
352 test_cmp expected actual
353 '
354
355 test_expect_success 'failed revert sets REVERT_HEAD' '
356 pristine_detach initial &&
357 test_must_fail git revert picked &&
358 test_cmp_rev picked REVERT_HEAD
359 '
360
361 test_expect_success 'successful revert does not set REVERT_HEAD' '
362 pristine_detach base &&
363 git revert base &&
364 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
365 test_must_fail git rev-parse --verify REVERT_HEAD
366 '
367
368 test_expect_success 'revert --no-commit sets REVERT_HEAD' '
369 pristine_detach base &&
370 git revert --no-commit base &&
371 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
372 test_cmp_rev base REVERT_HEAD
373 '
374
375 test_expect_success 'revert w/dirty tree does not set REVERT_HEAD' '
376 pristine_detach base &&
377 echo foo >foo &&
378 test_must_fail git revert base &&
379 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
380 test_must_fail git rev-parse --verify REVERT_HEAD
381 '
382
383 test_expect_success 'GIT_CHERRY_PICK_HELP does not suppress REVERT_HEAD' '
384 pristine_detach initial &&
385 (
386 GIT_CHERRY_PICK_HELP="and then do something else" &&
387 GIT_REVERT_HELP="and then do something else, again" &&
388 export GIT_CHERRY_PICK_HELP GIT_REVERT_HELP &&
389 test_must_fail git revert picked
390 ) &&
391 test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
392 test_cmp_rev picked REVERT_HEAD
393 '
394
395 test_expect_success 'git reset clears REVERT_HEAD' '
396 pristine_detach initial &&
397 test_must_fail git revert picked &&
398 git reset &&
399 test_must_fail git rev-parse --verify REVERT_HEAD
400 '
401
402 test_expect_success 'failed commit does not clear REVERT_HEAD' '
403 pristine_detach initial &&
404 test_must_fail git revert picked &&
405 test_must_fail git commit &&
406 test_cmp_rev picked REVERT_HEAD
407 '
408
409 test_expect_success 'successful final commit clears revert state' '
410 pristine_detach picked-signed &&
411
412 test_must_fail git revert picked-signed base &&
413 echo resolved >foo &&
414 test_path_is_file .git/sequencer/todo &&
415 git commit -a &&
416 test_path_is_missing .git/sequencer
417 '
418
419 test_expect_success 'reset after final pick clears revert state' '
420 pristine_detach picked-signed &&
421
422 test_must_fail git revert picked-signed base &&
423 echo resolved >foo &&
424 test_path_is_file .git/sequencer/todo &&
425 git reset &&
426 test_path_is_missing .git/sequencer
427 '
428
429 test_expect_success 'revert conflict, diff3 -m style' '
430 pristine_detach initial &&
431 git config merge.conflictstyle diff3 &&
432 cat <<-EOF >expected &&
433 <<<<<<< HEAD
434 a
435 ||||||| objid (picked)
436 c
437 =======
438 b
439 >>>>>>> parent of objid (picked)
440 EOF
441
442 test_must_fail git revert picked &&
443
444 sed "s/[a-f0-9]* (/objid (/" foo >actual &&
445 test_cmp expected actual
446 '
447
448 test_expect_success \
449 'revert conflict, ensure commit.cleanup = scissors places scissors line properly' '
450 pristine_detach initial &&
451 git config commit.cleanup scissors &&
452 cat >expected <<-EOF &&
453 Revert "picked"
454
455 This reverts commit OBJID.
456
457 # ------------------------ >8 ------------------------
458 # Do not modify or remove the line above.
459 # Everything below it will be ignored.
460 #
461 # Conflicts:
462 # foo
463 EOF
464
465 test_must_fail git revert picked &&
466
467 sed "s/$OID_REGEX/OBJID/" .git/MERGE_MSG >actual &&
468 test_cmp expected actual
469 '
470
471 test_expect_success \
472 'revert conflict, ensure cleanup=scissors places scissors line properly' '
473 pristine_detach initial &&
474 git config --unset commit.cleanup &&
475 cat >expected <<-EOF &&
476 Revert "picked"
477
478 This reverts commit OBJID.
479
480 # ------------------------ >8 ------------------------
481 # Do not modify or remove the line above.
482 # Everything below it will be ignored.
483 #
484 # Conflicts:
485 # foo
486 EOF
487
488 test_must_fail git revert --cleanup=scissors picked &&
489
490 sed "s/$OID_REGEX/OBJID/" .git/MERGE_MSG >actual &&
491 test_cmp expected actual
492 '
493
494 test_expect_success 'failed cherry-pick does not forget -s' '
495 pristine_detach initial &&
496 test_must_fail git cherry-pick -s picked &&
497 test_i18ngrep -e "Signed-off-by" .git/MERGE_MSG
498 '
499
500 test_expect_success 'commit after failed cherry-pick does not add duplicated -s' '
501 pristine_detach initial &&
502 test_must_fail git cherry-pick -s picked-signed &&
503 git commit -a -s &&
504 test $(git show -s >tmp && grep -c "Signed-off-by" tmp && rm tmp) = 1
505 '
506
507 test_expect_success 'commit after failed cherry-pick adds -s at the right place' '
508 pristine_detach initial &&
509 test_must_fail git cherry-pick picked &&
510
511 git commit -a -s &&
512
513 # Do S-o-b and Conflicts appear in the right order?
514 cat <<-\EOF >expect &&
515 Signed-off-by: C O Mitter <committer@example.com>
516 # Conflicts:
517 EOF
518 grep -e "^# Conflicts:" -e "^Signed-off-by" .git/COMMIT_EDITMSG >actual &&
519 test_cmp expect actual &&
520
521 cat <<-\EOF >expected &&
522 picked
523
524 Signed-off-by: C O Mitter <committer@example.com>
525 EOF
526
527 git show -s --pretty=format:%B >actual &&
528 test_cmp expected actual
529 '
530
531 test_expect_success 'commit --amend -s places the sign-off at the right place' '
532 pristine_detach initial &&
533 test_must_fail git cherry-pick picked &&
534
535 # emulate old-style conflicts block
536 mv .git/MERGE_MSG .git/MERGE_MSG+ &&
537 sed -e "/^# Conflicts:/,\$s/^# *//" .git/MERGE_MSG+ >.git/MERGE_MSG &&
538
539 git commit -a &&
540 git commit --amend -s &&
541
542 # Do S-o-b and Conflicts appear in the right order?
543 cat <<-\EOF >expect &&
544 Signed-off-by: C O Mitter <committer@example.com>
545 Conflicts:
546 EOF
547 grep -e "^Conflicts:" -e "^Signed-off-by" .git/COMMIT_EDITMSG >actual &&
548 test_cmp expect actual
549 '
550
551 test_expect_success 'cherry-pick preserves sparse-checkout' '
552 pristine_detach initial &&
553 test_config core.sparseCheckout true &&
554 test_when_finished "
555 echo \"/*\" >.git/info/sparse-checkout
556 git read-tree --reset -u HEAD
557 rm .git/info/sparse-checkout" &&
558 echo /unrelated >.git/info/sparse-checkout &&
559 git read-tree --reset -u HEAD &&
560 test_must_fail git cherry-pick -Xours picked>actual &&
561 test_i18ngrep ! "Changes not staged for commit:" actual
562 '
563
564 test_expect_success 'cherry-pick --continue remembers --keep-redundant-commits' '
565 test_when_finished "git cherry-pick --abort || :" &&
566 pristine_detach initial &&
567 test_must_fail git cherry-pick --keep-redundant-commits picked redundant &&
568 echo c >foo &&
569 git add foo &&
570 git cherry-pick --continue
571 '
572
573 test_expect_success 'cherry-pick --continue remembers --allow-empty and --allow-empty-message' '
574 test_when_finished "git cherry-pick --abort || :" &&
575 pristine_detach initial &&
576 test_must_fail git cherry-pick --allow-empty --allow-empty-message \
577 picked empty &&
578 echo c >foo &&
579 git add foo &&
580 git cherry-pick --continue
581 '
582
583 test_done