Imported Upstream version 2.27.0
[platform/upstream/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
165 test_expect_success 'partial commit of cherry-pick fails' '
166         pristine_detach initial &&
167
168         test_must_fail git cherry-pick picked &&
169         echo resolved >foo &&
170         git add foo &&
171         test_must_fail git commit foo 2>err &&
172
173         test_i18ngrep "cannot do a partial commit during a cherry-pick." err
174 '
175
176 test_expect_success 'commit --amend of cherry-pick fails' '
177         pristine_detach initial &&
178
179         test_must_fail git cherry-pick picked &&
180         echo resolved >foo &&
181         git add foo &&
182         test_must_fail git commit --amend 2>err &&
183
184         test_i18ngrep "in the middle of a cherry-pick -- cannot amend." err
185 '
186
187 test_expect_success 'successful final commit clears cherry-pick state' '
188         pristine_detach initial &&
189
190         test_must_fail git cherry-pick base picked-signed &&
191         echo resolved >foo &&
192         test_path_is_file .git/sequencer/todo &&
193         git commit -a &&
194         test_path_is_missing .git/sequencer
195 '
196
197 test_expect_success 'reset after final pick clears cherry-pick state' '
198         pristine_detach initial &&
199
200         test_must_fail git cherry-pick base picked-signed &&
201         echo resolved >foo &&
202         test_path_is_file .git/sequencer/todo &&
203         git reset &&
204         test_path_is_missing .git/sequencer
205 '
206
207 test_expect_success 'failed cherry-pick produces dirty index' '
208         pristine_detach initial &&
209
210         test_must_fail git cherry-pick picked &&
211
212         test_must_fail git update-index --refresh -q &&
213         test_must_fail git diff-index --exit-code HEAD
214 '
215
216 test_expect_success 'failed cherry-pick registers participants in index' '
217         pristine_detach initial &&
218         {
219                 git checkout base -- foo &&
220                 git ls-files --stage foo &&
221                 git checkout initial -- foo &&
222                 git ls-files --stage foo &&
223                 git checkout picked -- foo &&
224                 git ls-files --stage foo
225         } >stages &&
226         sed "
227                 1 s/ 0  / 1     /
228                 2 s/ 0  / 2     /
229                 3 s/ 0  / 3     /
230         " stages >expected &&
231         git read-tree -u --reset HEAD &&
232
233         test_must_fail git cherry-pick picked &&
234         git ls-files --stage --unmerged >actual &&
235
236         test_cmp expected actual
237 '
238
239 test_expect_success \
240         'cherry-pick conflict, ensure commit.cleanup = scissors places scissors line properly' '
241         pristine_detach initial &&
242         git config commit.cleanup scissors &&
243         cat <<-EOF >expected &&
244                 picked
245
246                 # ------------------------ >8 ------------------------
247                 # Do not modify or remove the line above.
248                 # Everything below it will be ignored.
249                 #
250                 # Conflicts:
251                 #       foo
252                 EOF
253
254         test_must_fail git cherry-pick picked &&
255
256         test_i18ncmp expected .git/MERGE_MSG
257 '
258
259 test_expect_success \
260         'cherry-pick conflict, ensure cleanup=scissors places scissors line properly' '
261         pristine_detach initial &&
262         git config --unset commit.cleanup &&
263         cat <<-EOF >expected &&
264                 picked
265
266                 # ------------------------ >8 ------------------------
267                 # Do not modify or remove the line above.
268                 # Everything below it will be ignored.
269                 #
270                 # Conflicts:
271                 #       foo
272                 EOF
273
274         test_must_fail git cherry-pick --cleanup=scissors picked &&
275
276         test_i18ncmp expected .git/MERGE_MSG
277 '
278
279 test_expect_success 'failed cherry-pick describes conflict in work tree' '
280         pristine_detach initial &&
281         cat <<-EOF >expected &&
282         <<<<<<< HEAD
283         a
284         =======
285         c
286         >>>>>>> objid picked
287         EOF
288
289         test_must_fail git cherry-pick picked &&
290
291         sed "s/[a-f0-9]*\.\.\./objid/" foo >actual &&
292         test_cmp expected actual
293 '
294
295 test_expect_success 'diff3 -m style' '
296         pristine_detach initial &&
297         git config merge.conflictstyle diff3 &&
298         cat <<-EOF >expected &&
299         <<<<<<< HEAD
300         a
301         ||||||| parent of objid picked
302         b
303         =======
304         c
305         >>>>>>> objid picked
306         EOF
307
308         test_must_fail git cherry-pick picked &&
309
310         sed "s/[a-f0-9]*\.\.\./objid/" foo >actual &&
311         test_cmp expected actual
312 '
313
314 test_expect_success 'revert also handles conflicts sanely' '
315         git config --unset merge.conflictstyle &&
316         pristine_detach initial &&
317         cat <<-EOF >expected &&
318         <<<<<<< HEAD
319         a
320         =======
321         b
322         >>>>>>> parent of objid picked
323         EOF
324         {
325                 git checkout picked -- foo &&
326                 git ls-files --stage foo &&
327                 git checkout initial -- foo &&
328                 git ls-files --stage foo &&
329                 git checkout base -- foo &&
330                 git ls-files --stage foo
331         } >stages &&
332         sed "
333                 1 s/ 0  / 1     /
334                 2 s/ 0  / 2     /
335                 3 s/ 0  / 3     /
336         " stages >expected-stages &&
337         git read-tree -u --reset HEAD &&
338
339         head=$(git rev-parse HEAD) &&
340         test_must_fail git revert picked &&
341         newhead=$(git rev-parse HEAD) &&
342         git ls-files --stage --unmerged >actual-stages &&
343
344         test "$head" = "$newhead" &&
345         test_must_fail git update-index --refresh -q &&
346         test_must_fail git diff-index --exit-code HEAD &&
347         test_cmp expected-stages actual-stages &&
348         sed "s/[a-f0-9]*\.\.\./objid/" foo >actual &&
349         test_cmp expected actual
350 '
351
352 test_expect_success 'failed revert sets REVERT_HEAD' '
353         pristine_detach initial &&
354         test_must_fail git revert picked &&
355         test_cmp_rev picked REVERT_HEAD
356 '
357
358 test_expect_success 'successful revert does not set REVERT_HEAD' '
359         pristine_detach base &&
360         git revert base &&
361         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
362         test_must_fail git rev-parse --verify REVERT_HEAD
363 '
364
365 test_expect_success 'revert --no-commit sets REVERT_HEAD' '
366         pristine_detach base &&
367         git revert --no-commit base &&
368         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
369         test_cmp_rev base REVERT_HEAD
370 '
371
372 test_expect_success 'revert w/dirty tree does not set REVERT_HEAD' '
373         pristine_detach base &&
374         echo foo >foo &&
375         test_must_fail git revert base &&
376         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
377         test_must_fail git rev-parse --verify REVERT_HEAD
378 '
379
380 test_expect_success 'GIT_CHERRY_PICK_HELP does not suppress REVERT_HEAD' '
381         pristine_detach initial &&
382         (
383                 GIT_CHERRY_PICK_HELP="and then do something else" &&
384                 GIT_REVERT_HELP="and then do something else, again" &&
385                 export GIT_CHERRY_PICK_HELP GIT_REVERT_HELP &&
386                 test_must_fail git revert picked
387         ) &&
388         test_must_fail git rev-parse --verify CHERRY_PICK_HEAD &&
389         test_cmp_rev picked REVERT_HEAD
390 '
391
392 test_expect_success 'git reset clears REVERT_HEAD' '
393         pristine_detach initial &&
394         test_must_fail git revert picked &&
395         git reset &&
396         test_must_fail git rev-parse --verify REVERT_HEAD
397 '
398
399 test_expect_success 'failed commit does not clear REVERT_HEAD' '
400         pristine_detach initial &&
401         test_must_fail git revert picked &&
402         test_must_fail git commit &&
403         test_cmp_rev picked REVERT_HEAD
404 '
405
406 test_expect_success 'successful final commit clears revert state' '
407         pristine_detach picked-signed &&
408
409         test_must_fail git revert picked-signed base &&
410         echo resolved >foo &&
411         test_path_is_file .git/sequencer/todo &&
412         git commit -a &&
413         test_path_is_missing .git/sequencer
414 '
415
416 test_expect_success 'reset after final pick clears revert state' '
417         pristine_detach picked-signed &&
418
419         test_must_fail git revert picked-signed base &&
420         echo resolved >foo &&
421         test_path_is_file .git/sequencer/todo &&
422         git reset &&
423         test_path_is_missing .git/sequencer
424 '
425
426 test_expect_success 'revert conflict, diff3 -m style' '
427         pristine_detach initial &&
428         git config merge.conflictstyle diff3 &&
429         cat <<-EOF >expected &&
430         <<<<<<< HEAD
431         a
432         ||||||| objid picked
433         c
434         =======
435         b
436         >>>>>>> parent of objid picked
437         EOF
438
439         test_must_fail git revert picked &&
440
441         sed "s/[a-f0-9]*\.\.\./objid/" foo >actual &&
442         test_cmp expected actual
443 '
444
445 test_expect_success \
446         'revert conflict, ensure commit.cleanup = scissors places scissors line properly' '
447         pristine_detach initial &&
448         git config commit.cleanup scissors &&
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 picked &&
463
464         sed "s/$OID_REGEX/OBJID/" .git/MERGE_MSG >actual &&
465         test_i18ncmp expected actual
466 '
467
468 test_expect_success \
469         'revert conflict, ensure cleanup=scissors places scissors line properly' '
470         pristine_detach initial &&
471         git config --unset commit.cleanup &&
472         cat >expected <<-EOF &&
473                 Revert "picked"
474
475                 This reverts commit OBJID.
476
477                 # ------------------------ >8 ------------------------
478                 # Do not modify or remove the line above.
479                 # Everything below it will be ignored.
480                 #
481                 # Conflicts:
482                 #       foo
483                 EOF
484
485         test_must_fail git revert --cleanup=scissors picked &&
486
487         sed "s/$OID_REGEX/OBJID/" .git/MERGE_MSG >actual &&
488         test_i18ncmp expected actual
489 '
490
491 test_expect_success 'failed cherry-pick does not forget -s' '
492         pristine_detach initial &&
493         test_must_fail git cherry-pick -s picked &&
494         test_i18ngrep -e "Signed-off-by" .git/MERGE_MSG
495 '
496
497 test_expect_success 'commit after failed cherry-pick does not add duplicated -s' '
498         pristine_detach initial &&
499         test_must_fail git cherry-pick -s picked-signed &&
500         git commit -a -s &&
501         test $(git show -s >tmp && grep -c "Signed-off-by" tmp && rm tmp) = 1
502 '
503
504 test_expect_success 'commit after failed cherry-pick adds -s at the right place' '
505         pristine_detach initial &&
506         test_must_fail git cherry-pick picked &&
507
508         git commit -a -s &&
509
510         # Do S-o-b and Conflicts appear in the right order?
511         cat <<-\EOF >expect &&
512         Signed-off-by: C O Mitter <committer@example.com>
513         # Conflicts:
514         EOF
515         grep -e "^# Conflicts:" -e '^Signed-off-by' .git/COMMIT_EDITMSG >actual &&
516         test_cmp expect actual &&
517
518         cat <<-\EOF >expected &&
519         picked
520
521         Signed-off-by: C O Mitter <committer@example.com>
522         EOF
523
524         git show -s --pretty=format:%B >actual &&
525         test_cmp expected actual
526 '
527
528 test_expect_success 'commit --amend -s places the sign-off at the right place' '
529         pristine_detach initial &&
530         test_must_fail git cherry-pick picked &&
531
532         # emulate old-style conflicts block
533         mv .git/MERGE_MSG .git/MERGE_MSG+ &&
534         sed -e "/^# Conflicts:/,\$s/^# *//" .git/MERGE_MSG+ >.git/MERGE_MSG &&
535
536         git commit -a &&
537         git commit --amend -s &&
538
539         # Do S-o-b and Conflicts appear in the right order?
540         cat <<-\EOF >expect &&
541         Signed-off-by: C O Mitter <committer@example.com>
542         Conflicts:
543         EOF
544         grep -e "^Conflicts:" -e '^Signed-off-by' .git/COMMIT_EDITMSG >actual &&
545         test_cmp expect actual
546 '
547
548 test_expect_success 'cherry-pick preserves sparse-checkout' '
549         pristine_detach initial &&
550         test_config core.sparseCheckout true &&
551         test_when_finished "
552                 echo \"/*\" >.git/info/sparse-checkout
553                 git read-tree --reset -u HEAD
554                 rm .git/info/sparse-checkout" &&
555         echo /unrelated >.git/info/sparse-checkout &&
556         git read-tree --reset -u HEAD &&
557         test_must_fail git cherry-pick -Xours picked>actual &&
558         test_i18ngrep ! "Changes not staged for commit:" actual
559 '
560
561 test_expect_success 'cherry-pick --continue remembers --keep-redundant-commits' '
562         test_when_finished "git cherry-pick --abort || :" &&
563         pristine_detach initial &&
564         test_must_fail git cherry-pick --keep-redundant-commits picked redundant &&
565         echo c >foo &&
566         git add foo &&
567         git cherry-pick --continue
568 '
569
570 test_expect_success 'cherry-pick --continue remembers --allow-empty and --allow-empty-message' '
571         test_when_finished "git cherry-pick --abort || :" &&
572         pristine_detach initial &&
573         test_must_fail git cherry-pick --allow-empty --allow-empty-message \
574                                        picked empty &&
575         echo c >foo &&
576         git add foo &&
577         git cherry-pick --continue
578 '
579
580 test_done