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