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