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