]> git.ipfire.org Git - thirdparty/git.git/blob - t/t6422-merge-rename-corner-cases.sh
t/: new helper for tests that pass with ort but fail with recursive
[thirdparty/git.git] / t / t6422-merge-rename-corner-cases.sh
1 #!/bin/sh
2
3 test_description="recursive merge corner cases w/ renames but not criss-crosses"
4 # t6036 has corner cases that involve both criss-cross merges and renames
5
6 . ./test-lib.sh
7 . "$TEST_DIRECTORY"/lib-merge.sh
8
9 test_setup_rename_delete_untracked () {
10 test_create_repo rename-delete-untracked &&
11 (
12 cd rename-delete-untracked &&
13
14 echo "A pretty inscription" >ring &&
15 git add ring &&
16 test_tick &&
17 git commit -m beginning &&
18
19 git branch people &&
20 git checkout -b rename-the-ring &&
21 git mv ring one-ring-to-rule-them-all &&
22 test_tick &&
23 git commit -m fullname &&
24
25 git checkout people &&
26 git rm ring &&
27 echo gollum >owner &&
28 git add owner &&
29 test_tick &&
30 git commit -m track-people-instead-of-objects &&
31 echo "Myyy PRECIOUSSS" >ring
32 )
33 }
34
35 test_expect_success "Does git preserve Gollum's precious artifact?" '
36 test_setup_rename_delete_untracked &&
37 (
38 cd rename-delete-untracked &&
39
40 test_must_fail git merge -s recursive rename-the-ring &&
41
42 # Make sure git did not delete an untracked file
43 test_path_is_file ring
44 )
45 '
46
47 # Testcase setup for rename/modify/add-source:
48 # Commit A: new file: a
49 # Commit B: modify a slightly
50 # Commit C: rename a->b, add completely different a
51 #
52 # We should be able to merge B & C cleanly
53
54 test_setup_rename_modify_add_source () {
55 test_create_repo rename-modify-add-source &&
56 (
57 cd rename-modify-add-source &&
58
59 printf "1\n2\n3\n4\n5\n6\n7\n" >a &&
60 git add a &&
61 git commit -m A &&
62 git tag A &&
63
64 git checkout -b B A &&
65 echo 8 >>a &&
66 git add a &&
67 git commit -m B &&
68
69 git checkout -b C A &&
70 git mv a b &&
71 echo something completely different >a &&
72 git add a &&
73 git commit -m C
74 )
75 }
76
77 test_expect_failure 'rename/modify/add-source conflict resolvable' '
78 test_setup_rename_modify_add_source &&
79 (
80 cd rename-modify-add-source &&
81
82 git checkout B^0 &&
83
84 git merge -s recursive C^0 &&
85
86 git rev-parse >expect \
87 B:a C:a &&
88 git rev-parse >actual \
89 b c &&
90 test_cmp expect actual
91 )
92 '
93
94 test_setup_break_detection_1 () {
95 test_create_repo break-detection-1 &&
96 (
97 cd break-detection-1 &&
98
99 printf "1\n2\n3\n4\n5\n" >a &&
100 echo foo >b &&
101 git add a b &&
102 git commit -m A &&
103 git tag A &&
104
105 git checkout -b B A &&
106 git mv a c &&
107 echo "Completely different content" >a &&
108 git add a &&
109 git commit -m B &&
110
111 git checkout -b C A &&
112 echo 6 >>a &&
113 git add a &&
114 git commit -m C
115 )
116 }
117
118 test_expect_failure 'conflict caused if rename not detected' '
119 test_setup_break_detection_1 &&
120 (
121 cd break-detection-1 &&
122
123 git checkout -q C^0 &&
124 git merge -s recursive B^0 &&
125
126 git ls-files -s >out &&
127 test_line_count = 3 out &&
128 git ls-files -u >out &&
129 test_line_count = 0 out &&
130 git ls-files -o >out &&
131 test_line_count = 1 out &&
132
133 test_line_count = 6 c &&
134 git rev-parse >expect \
135 B:a A:b &&
136 git rev-parse >actual \
137 :0:a :0:b &&
138 test_cmp expect actual
139 )
140 '
141
142 test_setup_break_detection_2 () {
143 test_create_repo break-detection-2 &&
144 (
145 cd break-detection-2 &&
146
147 printf "1\n2\n3\n4\n5\n" >a &&
148 echo foo >b &&
149 git add a b &&
150 git commit -m A &&
151 git tag A &&
152
153 git checkout -b D A &&
154 echo 7 >>a &&
155 git add a &&
156 git mv a c &&
157 echo "Completely different content" >a &&
158 git add a &&
159 git commit -m D &&
160
161 git checkout -b E A &&
162 git rm a &&
163 echo "Completely different content" >>a &&
164 git add a &&
165 git commit -m E
166 )
167 }
168
169 test_expect_failure 'missed conflict if rename not detected' '
170 test_setup_break_detection_2 &&
171 (
172 cd break-detection-2 &&
173
174 git checkout -q E^0 &&
175 test_must_fail git merge -s recursive D^0
176 )
177 '
178
179 # Tests for undetected rename/add-source causing a file to erroneously be
180 # deleted (and for mishandled rename/rename(1to1) causing the same issue).
181 #
182 # This test uses a rename/rename(1to1)+add-source conflict (1to1 means the
183 # same file is renamed on both sides to the same thing; it should trigger
184 # the 1to2 logic, which it would do if the add-source didn't cause issues
185 # for git's rename detection):
186 # Commit A: new file: a
187 # Commit B: rename a->b
188 # Commit C: rename a->b, add unrelated a
189
190 test_setup_break_detection_3 () {
191 test_create_repo break-detection-3 &&
192 (
193 cd break-detection-3 &&
194
195 printf "1\n2\n3\n4\n5\n" >a &&
196 git add a &&
197 git commit -m A &&
198 git tag A &&
199
200 git checkout -b B A &&
201 git mv a b &&
202 git commit -m B &&
203
204 git checkout -b C A &&
205 git mv a b &&
206 echo foobar >a &&
207 git add a &&
208 git commit -m C
209 )
210 }
211
212 test_expect_failure 'detect rename/add-source and preserve all data' '
213 test_setup_break_detection_3 &&
214 (
215 cd break-detection-3 &&
216
217 git checkout B^0 &&
218
219 git merge -s recursive C^0 &&
220
221 git ls-files -s >out &&
222 test_line_count = 2 out &&
223 git ls-files -u >out &&
224 test_line_count = 2 out &&
225 git ls-files -o >out &&
226 test_line_count = 1 out &&
227
228 test_path_is_file a &&
229 test_path_is_file b &&
230
231 git rev-parse >expect \
232 A:a C:a &&
233 git rev-parse >actual \
234 :0:b :0:a &&
235 test_cmp expect actual
236 )
237 '
238
239 test_expect_failure 'detect rename/add-source and preserve all data, merge other way' '
240 test_setup_break_detection_3 &&
241 (
242 cd break-detection-3 &&
243
244 git checkout C^0 &&
245
246 git merge -s recursive B^0 &&
247
248 git ls-files -s >out &&
249 test_line_count = 2 out &&
250 git ls-files -u >out &&
251 test_line_count = 2 out &&
252 git ls-files -o >out &&
253 test_line_count = 1 out &&
254
255 test_path_is_file a &&
256 test_path_is_file b &&
257
258 git rev-parse >expect \
259 A:a C:a &&
260 git rev-parse >actual \
261 :0:b :0:a &&
262 test_cmp expect actual
263 )
264 '
265
266 test_setup_rename_directory () {
267 test_create_repo rename-directory-$1 &&
268 (
269 cd rename-directory-$1 &&
270
271 printf "1\n2\n3\n4\n5\n6\n" >file &&
272 git add file &&
273 test_tick &&
274 git commit -m base &&
275 git tag base &&
276
277 git checkout -b right &&
278 echo 7 >>file &&
279 mkdir newfile &&
280 echo junk >newfile/realfile &&
281 git add file newfile/realfile &&
282 test_tick &&
283 git commit -m right &&
284
285 git checkout -b left-conflict base &&
286 echo 8 >>file &&
287 git add file &&
288 git mv file newfile &&
289 test_tick &&
290 git commit -m left &&
291
292 git checkout -b left-clean base &&
293 echo 0 >newfile &&
294 cat file >>newfile &&
295 git add newfile &&
296 git rm file &&
297 test_tick &&
298 git commit -m left
299 )
300 }
301
302 test_expect_success 'rename/directory conflict + clean content merge' '
303 test_setup_rename_directory 1a &&
304 (
305 cd rename-directory-1a &&
306
307 git checkout left-clean^0 &&
308
309 test_must_fail git merge -s recursive right^0 &&
310
311 git ls-files -s >out &&
312 test_line_count = 2 out &&
313 git ls-files -u >out &&
314 test_line_count = 1 out &&
315 git ls-files -o >out &&
316 test_line_count = 2 out &&
317
318 echo 0 >expect &&
319 git cat-file -p base:file >>expect &&
320 echo 7 >>expect &&
321 test_cmp expect newfile~HEAD &&
322
323 test $(git rev-parse :2:newfile) = $(git hash-object expect) &&
324
325 test_path_is_file newfile/realfile &&
326 test_path_is_file newfile~HEAD
327 )
328 '
329
330 test_expect_success 'rename/directory conflict + content merge conflict' '
331 test_setup_rename_directory 1b &&
332 (
333 cd rename-directory-1b &&
334
335 git reset --hard &&
336 git clean -fdqx &&
337
338 git checkout left-conflict^0 &&
339
340 test_must_fail git merge -s recursive right^0 &&
341
342 git ls-files -s >out &&
343 test_line_count = 4 out &&
344 git ls-files -u >out &&
345 test_line_count = 3 out &&
346 git ls-files -o >out &&
347 test_line_count = 2 out &&
348
349 git cat-file -p left-conflict:newfile >left &&
350 git cat-file -p base:file >base &&
351 git cat-file -p right:file >right &&
352 test_must_fail git merge-file \
353 -L "HEAD:newfile" \
354 -L "" \
355 -L "right^0:file" \
356 left base right &&
357 test_cmp left newfile~HEAD &&
358
359 git rev-parse >expect \
360 base:file left-conflict:newfile right:file &&
361 git rev-parse >actual \
362 :1:newfile :2:newfile :3:newfile &&
363 test_cmp expect actual &&
364
365 test_path_is_file newfile/realfile &&
366 test_path_is_file newfile~HEAD
367 )
368 '
369
370 test_setup_rename_directory_2 () {
371 test_create_repo rename-directory-2 &&
372 (
373 cd rename-directory-2 &&
374
375 mkdir sub &&
376 printf "1\n2\n3\n4\n5\n6\n" >sub/file &&
377 git add sub/file &&
378 test_tick &&
379 git commit -m base &&
380 git tag base &&
381
382 git checkout -b right &&
383 echo 7 >>sub/file &&
384 git add sub/file &&
385 test_tick &&
386 git commit -m right &&
387
388 git checkout -b left base &&
389 echo 0 >newfile &&
390 cat sub/file >>newfile &&
391 git rm sub/file &&
392 mv newfile sub &&
393 git add sub &&
394 test_tick &&
395 git commit -m left
396 )
397 }
398
399 test_expect_success 'disappearing dir in rename/directory conflict handled' '
400 test_setup_rename_directory_2 &&
401 (
402 cd rename-directory-2 &&
403
404 git checkout left^0 &&
405
406 git merge -s recursive right^0 &&
407
408 git ls-files -s >out &&
409 test_line_count = 1 out &&
410 git ls-files -u >out &&
411 test_line_count = 0 out &&
412 git ls-files -o >out &&
413 test_line_count = 1 out &&
414
415 echo 0 >expect &&
416 git cat-file -p base:sub/file >>expect &&
417 echo 7 >>expect &&
418 test_cmp expect sub &&
419
420 test_path_is_file sub
421 )
422 '
423
424 # Test for basic rename/add-dest conflict, with rename needing content merge:
425 # Commit O: a
426 # Commit A: rename a->b, modifying b too
427 # Commit B: modify a, add different b
428
429 test_setup_rename_with_content_merge_and_add () {
430 test_create_repo rename-with-content-merge-and-add-$1 &&
431 (
432 cd rename-with-content-merge-and-add-$1 &&
433
434 test_seq 1 5 >a &&
435 git add a &&
436 git commit -m O &&
437 git tag O &&
438
439 git checkout -b A O &&
440 git mv a b &&
441 test_seq 0 5 >b &&
442 git add b &&
443 git commit -m A &&
444
445 git checkout -b B O &&
446 echo 6 >>a &&
447 echo hello world >b &&
448 git add a b &&
449 git commit -m B
450 )
451 }
452
453 test_expect_success 'handle rename-with-content-merge vs. add' '
454 test_setup_rename_with_content_merge_and_add AB &&
455 (
456 cd rename-with-content-merge-and-add-AB &&
457
458 git checkout A^0 &&
459
460 test_must_fail git merge -s recursive B^0 >out &&
461 test_i18ngrep "CONFLICT (.*/add)" out &&
462
463 git ls-files -s >out &&
464 test_line_count = 2 out &&
465 git ls-files -u >out &&
466 test_line_count = 2 out &&
467 # Also, make sure both unmerged entries are for "b"
468 git ls-files -u b >out &&
469 test_line_count = 2 out &&
470 git ls-files -o >out &&
471 test_line_count = 1 out &&
472
473 test_path_is_missing a &&
474 test_path_is_file b &&
475
476 test_seq 0 6 >tmp &&
477 git hash-object tmp >expect &&
478 git rev-parse B:b >>expect &&
479 git rev-parse >actual \
480 :2:b :3:b &&
481 test_cmp expect actual &&
482
483 # Test that the two-way merge in b is as expected
484 git cat-file -p :2:b >>ours &&
485 git cat-file -p :3:b >>theirs &&
486 >empty &&
487 test_must_fail git merge-file \
488 -L "HEAD" \
489 -L "" \
490 -L "B^0" \
491 ours empty theirs &&
492 test_cmp ours b
493 )
494 '
495
496 test_expect_success 'handle rename-with-content-merge vs. add, merge other way' '
497 test_setup_rename_with_content_merge_and_add BA &&
498 (
499 cd rename-with-content-merge-and-add-BA &&
500
501 git reset --hard &&
502 git clean -fdx &&
503
504 git checkout B^0 &&
505
506 test_must_fail git merge -s recursive A^0 >out &&
507 test_i18ngrep "CONFLICT (.*/add)" out &&
508
509 git ls-files -s >out &&
510 test_line_count = 2 out &&
511 git ls-files -u >out &&
512 test_line_count = 2 out &&
513 # Also, make sure both unmerged entries are for "b"
514 git ls-files -u b >out &&
515 test_line_count = 2 out &&
516 git ls-files -o >out &&
517 test_line_count = 1 out &&
518
519 test_path_is_missing a &&
520 test_path_is_file b &&
521
522 test_seq 0 6 >tmp &&
523 git rev-parse B:b >expect &&
524 git hash-object tmp >>expect &&
525 git rev-parse >actual \
526 :2:b :3:b &&
527 test_cmp expect actual &&
528
529 # Test that the two-way merge in b is as expected
530 git cat-file -p :2:b >>ours &&
531 git cat-file -p :3:b >>theirs &&
532 >empty &&
533 test_must_fail git merge-file \
534 -L "HEAD" \
535 -L "" \
536 -L "A^0" \
537 ours empty theirs &&
538 test_cmp ours b
539 )
540 '
541
542 # Test for all kinds of things that can go wrong with rename/rename (2to1):
543 # Commit A: new files: a & b
544 # Commit B: rename a->c, modify b
545 # Commit C: rename b->c, modify a
546 #
547 # Merging of B & C should NOT be clean. Questions:
548 # * Both a & b should be removed by the merge; are they?
549 # * The two c's should contain modifications to a & b; do they?
550 # * The index should contain two files, both for c; does it?
551 # * The working copy should have two files, both of form c~<unique>; does it?
552 # * Nothing else should be present. Is anything?
553
554 test_setup_rename_rename_2to1 () {
555 test_create_repo rename-rename-2to1 &&
556 (
557 cd rename-rename-2to1 &&
558
559 printf "1\n2\n3\n4\n5\n" >a &&
560 printf "5\n4\n3\n2\n1\n" >b &&
561 git add a b &&
562 git commit -m A &&
563 git tag A &&
564
565 git checkout -b B A &&
566 git mv a c &&
567 echo 0 >>b &&
568 git add b &&
569 git commit -m B &&
570
571 git checkout -b C A &&
572 git mv b c &&
573 echo 6 >>a &&
574 git add a &&
575 git commit -m C
576 )
577 }
578
579 test_expect_success 'handle rename/rename (2to1) conflict correctly' '
580 test_setup_rename_rename_2to1 &&
581 (
582 cd rename-rename-2to1 &&
583
584 git checkout B^0 &&
585
586 test_must_fail git merge -s recursive C^0 >out &&
587 test_i18ngrep "CONFLICT (\(.*\)/\1)" out &&
588
589 git ls-files -s >out &&
590 test_line_count = 2 out &&
591 git ls-files -u >out &&
592 test_line_count = 2 out &&
593 git ls-files -u c >out &&
594 test_line_count = 2 out &&
595 git ls-files -o >out &&
596 test_line_count = 1 out &&
597
598 test_path_is_missing a &&
599 test_path_is_missing b &&
600
601 git rev-parse >expect \
602 C:a B:b &&
603 git rev-parse >actual \
604 :2:c :3:c &&
605 test_cmp expect actual &&
606
607 # Test that the two-way merge in new_a is as expected
608 git cat-file -p :2:c >>ours &&
609 git cat-file -p :3:c >>theirs &&
610 >empty &&
611 test_must_fail git merge-file \
612 -L "HEAD" \
613 -L "" \
614 -L "C^0" \
615 ours empty theirs &&
616 git hash-object c >actual &&
617 git hash-object ours >expect &&
618 test_cmp expect actual
619 )
620 '
621
622 # Testcase setup for simple rename/rename (1to2) conflict:
623 # Commit A: new file: a
624 # Commit B: rename a->b
625 # Commit C: rename a->c
626 test_setup_rename_rename_1to2 () {
627 test_create_repo rename-rename-1to2 &&
628 (
629 cd rename-rename-1to2 &&
630
631 echo stuff >a &&
632 git add a &&
633 test_tick &&
634 git commit -m A &&
635 git tag A &&
636
637 git checkout -b B A &&
638 git mv a b &&
639 test_tick &&
640 git commit -m B &&
641
642 git checkout -b C A &&
643 git mv a c &&
644 test_tick &&
645 git commit -m C
646 )
647 }
648
649 test_expect_success 'merge has correct working tree contents' '
650 test_setup_rename_rename_1to2 &&
651 (
652 cd rename-rename-1to2 &&
653
654 git checkout C^0 &&
655
656 test_must_fail git merge -s recursive B^0 &&
657
658 git ls-files -s >out &&
659 test_line_count = 3 out &&
660 git ls-files -u >out &&
661 test_line_count = 3 out &&
662 git ls-files -o >out &&
663 test_line_count = 1 out &&
664
665 test_path_is_missing a &&
666 git rev-parse >expect \
667 A:a A:a A:a \
668 A:a A:a &&
669 git rev-parse >actual \
670 :1:a :3:b :2:c &&
671 git hash-object >>actual \
672 b c &&
673 test_cmp expect actual
674 )
675 '
676
677 # Testcase setup for rename/rename(1to2)/add-source conflict:
678 # Commit A: new file: a
679 # Commit B: rename a->b
680 # Commit C: rename a->c, add completely different a
681 #
682 # Merging of B & C should NOT be clean; there's a rename/rename conflict
683
684 test_setup_rename_rename_1to2_add_source_1 () {
685 test_create_repo rename-rename-1to2-add-source-1 &&
686 (
687 cd rename-rename-1to2-add-source-1 &&
688
689 printf "1\n2\n3\n4\n5\n6\n7\n" >a &&
690 git add a &&
691 git commit -m A &&
692 git tag A &&
693
694 git checkout -b B A &&
695 git mv a b &&
696 git commit -m B &&
697
698 git checkout -b C A &&
699 git mv a c &&
700 echo something completely different >a &&
701 git add a &&
702 git commit -m C
703 )
704 }
705
706 test_expect_failure 'detect conflict with rename/rename(1to2)/add-source merge' '
707 test_setup_rename_rename_1to2_add_source_1 &&
708 (
709 cd rename-rename-1to2-add-source-1 &&
710
711 git checkout B^0 &&
712
713 test_must_fail git merge -s recursive C^0 &&
714
715 git ls-files -s >out &&
716 test_line_count = 4 out &&
717 git ls-files -o >out &&
718 test_line_count = 1 out &&
719
720 git rev-parse >expect \
721 C:a A:a B:b C:C &&
722 git rev-parse >actual \
723 :3:a :1:a :2:b :3:c &&
724 test_cmp expect actual &&
725
726 test_path_is_file a &&
727 test_path_is_file b &&
728 test_path_is_file c
729 )
730 '
731
732 test_setup_rename_rename_1to2_add_source_2 () {
733 test_create_repo rename-rename-1to2-add-source-2 &&
734 (
735 cd rename-rename-1to2-add-source-2 &&
736
737 >a &&
738 git add a &&
739 test_tick &&
740 git commit -m base &&
741 git tag A &&
742
743 git checkout -b B A &&
744 git mv a b &&
745 test_tick &&
746 git commit -m one &&
747
748 git checkout -b C A &&
749 git mv a b &&
750 echo important-info >a &&
751 git add a &&
752 test_tick &&
753 git commit -m two
754 )
755 }
756
757 test_expect_failure 'rename/rename/add-source still tracks new a file' '
758 test_setup_rename_rename_1to2_add_source_2 &&
759 (
760 cd rename-rename-1to2-add-source-2 &&
761
762 git checkout C^0 &&
763 git merge -s recursive B^0 &&
764
765 git ls-files -s >out &&
766 test_line_count = 2 out &&
767 git ls-files -o >out &&
768 test_line_count = 1 out &&
769
770 git rev-parse >expect \
771 C:a A:a &&
772 git rev-parse >actual \
773 :0:a :0:b &&
774 test_cmp expect actual
775 )
776 '
777
778 test_setup_rename_rename_1to2_add_dest () {
779 test_create_repo rename-rename-1to2-add-dest &&
780 (
781 cd rename-rename-1to2-add-dest &&
782
783 echo stuff >a &&
784 git add a &&
785 test_tick &&
786 git commit -m base &&
787 git tag A &&
788
789 git checkout -b B A &&
790 git mv a b &&
791 echo precious-data >c &&
792 git add c &&
793 test_tick &&
794 git commit -m one &&
795
796 git checkout -b C A &&
797 git mv a c &&
798 echo important-info >b &&
799 git add b &&
800 test_tick &&
801 git commit -m two
802 )
803 }
804
805 test_expect_success 'rename/rename/add-dest merge still knows about conflicting file versions' '
806 test_setup_rename_rename_1to2_add_dest &&
807 (
808 cd rename-rename-1to2-add-dest &&
809
810 git checkout C^0 &&
811 test_must_fail git merge -s recursive B^0 &&
812
813 git ls-files -s >out &&
814 test_line_count = 5 out &&
815 git ls-files -u b >out &&
816 test_line_count = 2 out &&
817 git ls-files -u c >out &&
818 test_line_count = 2 out &&
819 git ls-files -o >out &&
820 test_line_count = 1 out &&
821
822 git rev-parse >expect \
823 A:a C:b B:b C:c B:c &&
824 git rev-parse >actual \
825 :1:a :2:b :3:b :2:c :3:c &&
826 test_cmp expect actual &&
827
828 # Record some contents for re-doing merges
829 git cat-file -p A:a >stuff &&
830 git cat-file -p C:b >important_info &&
831 git cat-file -p B:c >precious_data &&
832 >empty &&
833
834 # Test the merge in b
835 test_must_fail git merge-file \
836 -L "HEAD" \
837 -L "" \
838 -L "B^0" \
839 important_info empty stuff &&
840 test_cmp important_info b &&
841
842 # Test the merge in c
843 test_must_fail git merge-file \
844 -L "HEAD" \
845 -L "" \
846 -L "B^0" \
847 stuff empty precious_data &&
848 test_cmp stuff c
849 )
850 '
851
852 # Testcase rad, rename/add/delete
853 # Commit O: foo
854 # Commit A: rm foo, add different bar
855 # Commit B: rename foo->bar
856 # Expected: CONFLICT (rename/add/delete), two-way merged bar
857
858 test_setup_rad () {
859 test_create_repo rad &&
860 (
861 cd rad &&
862 echo "original file" >foo &&
863 git add foo &&
864 git commit -m "original" &&
865
866 git branch O &&
867 git branch A &&
868 git branch B &&
869
870 git checkout A &&
871 git rm foo &&
872 echo "different file" >bar &&
873 git add bar &&
874 git commit -m "Remove foo, add bar" &&
875
876 git checkout B &&
877 git mv foo bar &&
878 git commit -m "rename foo to bar"
879 )
880 }
881
882 test_expect_merge_algorithm failure success 'rad-check: rename/add/delete conflict' '
883 test_setup_rad &&
884 (
885 cd rad &&
886
887 git checkout B^0 &&
888 test_must_fail git merge -s recursive A^0 >out 2>err &&
889
890 # Instead of requiring the output to contain one combined line
891 # CONFLICT (rename/add/delete)
892 # or perhaps two lines:
893 # CONFLICT (rename/add): new file collides with rename target
894 # CONFLICT (rename/delete): rename source removed on other side
895 # and instead of requiring "rename/add" instead of "add/add",
896 # be flexible in the type of console output message(s) reported
897 # for this particular case; we will be more stringent about the
898 # contents of the index and working directory.
899 test_i18ngrep "CONFLICT (.*/add)" out &&
900 test_i18ngrep "CONFLICT (rename.*/delete)" out &&
901 test_must_be_empty err &&
902
903 git ls-files -s >file_count &&
904 test_line_count = 2 file_count &&
905 git ls-files -u >file_count &&
906 test_line_count = 2 file_count &&
907 git ls-files -o >file_count &&
908 test_line_count = 3 file_count &&
909
910 git rev-parse >actual \
911 :2:bar :3:bar &&
912 git rev-parse >expect \
913 B:bar A:bar &&
914
915 test_path_is_missing foo &&
916 # bar should have two-way merged contents of the different
917 # versions of bar; check that content from both sides is
918 # present.
919 grep original bar &&
920 grep different bar
921 )
922 '
923
924 # Testcase rrdd, rename/rename(2to1)/delete/delete
925 # Commit O: foo, bar
926 # Commit A: rename foo->baz, rm bar
927 # Commit B: rename bar->baz, rm foo
928 # Expected: CONFLICT (rename/rename/delete/delete), two-way merged baz
929
930 test_setup_rrdd () {
931 test_create_repo rrdd &&
932 (
933 cd rrdd &&
934 echo foo >foo &&
935 echo bar >bar &&
936 git add foo bar &&
937 git commit -m O &&
938
939 git branch O &&
940 git branch A &&
941 git branch B &&
942
943 git checkout A &&
944 git mv foo baz &&
945 git rm bar &&
946 git commit -m "Rename foo, remove bar" &&
947
948 git checkout B &&
949 git mv bar baz &&
950 git rm foo &&
951 git commit -m "Rename bar, remove foo"
952 )
953 }
954
955 test_expect_merge_algorithm failure success 'rrdd-check: rename/rename(2to1)/delete/delete conflict' '
956 test_setup_rrdd &&
957 (
958 cd rrdd &&
959
960 git checkout A^0 &&
961 test_must_fail git merge -s recursive B^0 >out 2>err &&
962
963 # Instead of requiring the output to contain one combined line
964 # CONFLICT (rename/rename/delete/delete)
965 # or perhaps two lines:
966 # CONFLICT (rename/rename): ...
967 # CONFLICT (rename/delete): info about pair 1
968 # CONFLICT (rename/delete): info about pair 2
969 # and instead of requiring "rename/rename" instead of "add/add",
970 # be flexible in the type of console output message(s) reported
971 # for this particular case; we will be more stringent about the
972 # contents of the index and working directory.
973 test_i18ngrep "CONFLICT (\(.*\)/\1)" out &&
974 test_i18ngrep "CONFLICT (rename.*delete)" out &&
975 test_must_be_empty err &&
976
977 git ls-files -s >file_count &&
978 test_line_count = 2 file_count &&
979 git ls-files -u >file_count &&
980 test_line_count = 2 file_count &&
981 git ls-files -o >file_count &&
982 test_line_count = 3 file_count &&
983
984 git rev-parse >actual \
985 :2:baz :3:baz &&
986 git rev-parse >expect \
987 O:foo O:bar &&
988
989 test_path_is_missing foo &&
990 test_path_is_missing bar &&
991 # baz should have two-way merged contents of the original
992 # contents of foo and bar; check that content from both sides
993 # is present.
994 grep foo baz &&
995 grep bar baz
996 )
997 '
998
999 # Testcase mod6, chains of rename/rename(1to2) and rename/rename(2to1)
1000 # Commit O: one, three, five
1001 # Commit A: one->two, three->four, five->six
1002 # Commit B: one->six, three->two, five->four
1003 # Expected: six CONFLICT(rename/rename) messages, each path in two of the
1004 # multi-way merged contents found in two, four, six
1005
1006 test_setup_mod6 () {
1007 test_create_repo mod6 &&
1008 (
1009 cd mod6 &&
1010 test_seq 11 19 >one &&
1011 test_seq 31 39 >three &&
1012 test_seq 51 59 >five &&
1013 git add . &&
1014 test_tick &&
1015 git commit -m "O" &&
1016
1017 git branch O &&
1018 git branch A &&
1019 git branch B &&
1020
1021 git checkout A &&
1022 test_seq 10 19 >one &&
1023 echo 40 >>three &&
1024 git add one three &&
1025 git mv one two &&
1026 git mv three four &&
1027 git mv five six &&
1028 test_tick &&
1029 git commit -m "A" &&
1030
1031 git checkout B &&
1032 echo 20 >>one &&
1033 echo forty >>three &&
1034 echo 60 >>five &&
1035 git add one three five &&
1036 git mv one six &&
1037 git mv three two &&
1038 git mv five four &&
1039 test_tick &&
1040 git commit -m "B"
1041 )
1042 }
1043
1044 test_expect_merge_algorithm failure success 'mod6-check: chains of rename/rename(1to2) and rename/rename(2to1)' '
1045 test_setup_mod6 &&
1046 (
1047 cd mod6 &&
1048
1049 git checkout A^0 &&
1050
1051 test_must_fail git merge -s recursive B^0 >out 2>err &&
1052
1053 test_i18ngrep "CONFLICT (rename/rename)" out &&
1054 test_must_be_empty err &&
1055
1056 git ls-files -s >file_count &&
1057 test_line_count = 9 file_count &&
1058 git ls-files -u >file_count &&
1059 test_line_count = 9 file_count &&
1060 git ls-files -o >file_count &&
1061 test_line_count = 3 file_count &&
1062
1063 test_seq 10 20 >merged-one &&
1064 test_seq 51 60 >merged-five &&
1065 # Determine what the merge of three would give us.
1066 test_seq 31 39 >three-base &&
1067 test_seq 31 40 >three-side-A &&
1068 test_seq 31 39 >three-side-B &&
1069 echo forty >>three-side-B &&
1070 test_must_fail git merge-file \
1071 -L "HEAD:four" \
1072 -L "" \
1073 -L "B^0:two" \
1074 three-side-A three-base three-side-B &&
1075 sed -e "s/^\([<=>]\)/\1\1/" three-side-A >merged-three &&
1076
1077 # Verify the index is as expected
1078 git rev-parse >actual \
1079 :2:two :3:two \
1080 :2:four :3:four \
1081 :2:six :3:six &&
1082 git hash-object >expect \
1083 merged-one merged-three \
1084 merged-three merged-five \
1085 merged-five merged-one &&
1086 test_cmp expect actual &&
1087
1088 git cat-file -p :2:two >expect &&
1089 git cat-file -p :3:two >other &&
1090 >empty &&
1091 test_must_fail git merge-file \
1092 -L "HEAD" -L "" -L "B^0" \
1093 expect empty other &&
1094 test_cmp expect two &&
1095
1096 git cat-file -p :2:four >expect &&
1097 git cat-file -p :3:four >other &&
1098 test_must_fail git merge-file \
1099 -L "HEAD" -L "" -L "B^0" \
1100 expect empty other &&
1101 test_cmp expect four &&
1102
1103 git cat-file -p :2:six >expect &&
1104 git cat-file -p :3:six >other &&
1105 test_must_fail git merge-file \
1106 -L "HEAD" -L "" -L "B^0" \
1107 expect empty other &&
1108 test_cmp expect six
1109 )
1110 '
1111
1112 test_conflicts_with_adds_and_renames() {
1113 sideL=$1
1114 sideR=$2
1115
1116 # Setup:
1117 # L
1118 # / \
1119 # master ?
1120 # \ /
1121 # R
1122 #
1123 # Where:
1124 # Both L and R have files named 'three' which collide. Each of
1125 # the colliding files could have been involved in a rename, in
1126 # which case there was a file named 'one' or 'two' that was
1127 # modified on the opposite side of history and renamed into the
1128 # collision on this side of history.
1129 #
1130 # Questions:
1131 # 1) The index should contain both a stage 2 and stage 3 entry
1132 # for the colliding file. Does it?
1133 # 2) When renames are involved, the content merges are clean, so
1134 # the index should reflect the content merges, not merely the
1135 # version of the colliding file from the prior commit. Does
1136 # it?
1137 # 3) There should be a file in the worktree named 'three'
1138 # containing the two-way merged contents of the content-merged
1139 # versions of 'three' from each of the two colliding
1140 # files. Is it present?
1141 # 4) There should not be any three~* files in the working
1142 # tree
1143 test_setup_collision_conflict () {
1144 #test_expect_success "setup simple $sideL/$sideR conflict" '
1145 test_create_repo simple_${sideL}_${sideR} &&
1146 (
1147 cd simple_${sideL}_${sideR} &&
1148
1149 # Create some related files now
1150 for i in $(test_seq 1 10)
1151 do
1152 echo Random base content line $i
1153 done >file_v1 &&
1154 cp file_v1 file_v2 &&
1155 echo modification >>file_v2 &&
1156
1157 cp file_v1 file_v3 &&
1158 echo more stuff >>file_v3 &&
1159 cp file_v3 file_v4 &&
1160 echo yet more stuff >>file_v4 &&
1161
1162 # Use a tag to record both these files for simple
1163 # access, and clean out these untracked files
1164 git tag file_v1 $(git hash-object -w file_v1) &&
1165 git tag file_v2 $(git hash-object -w file_v2) &&
1166 git tag file_v3 $(git hash-object -w file_v3) &&
1167 git tag file_v4 $(git hash-object -w file_v4) &&
1168 git clean -f &&
1169
1170 # Setup original commit (or merge-base), consisting of
1171 # files named "one" and "two" if renames were involved.
1172 touch irrelevant_file &&
1173 git add irrelevant_file &&
1174 if [ $sideL = "rename" ]
1175 then
1176 git show file_v1 >one &&
1177 git add one
1178 fi &&
1179 if [ $sideR = "rename" ]
1180 then
1181 git show file_v3 >two &&
1182 git add two
1183 fi &&
1184 test_tick && git commit -m initial &&
1185
1186 git branch L &&
1187 git branch R &&
1188
1189 # Handle the left side
1190 git checkout L &&
1191 if [ $sideL = "rename" ]
1192 then
1193 git mv one three
1194 else
1195 git show file_v2 >three &&
1196 git add three
1197 fi &&
1198 if [ $sideR = "rename" ]
1199 then
1200 git show file_v4 >two &&
1201 git add two
1202 fi &&
1203 test_tick && git commit -m L &&
1204
1205 # Handle the right side
1206 git checkout R &&
1207 if [ $sideL = "rename" ]
1208 then
1209 git show file_v2 >one &&
1210 git add one
1211 fi &&
1212 if [ $sideR = "rename" ]
1213 then
1214 git mv two three
1215 else
1216 git show file_v4 >three &&
1217 git add three
1218 fi &&
1219 test_tick && git commit -m R
1220 )
1221 #'
1222 }
1223
1224 test_expect_success "check simple $sideL/$sideR conflict" '
1225 test_setup_collision_conflict &&
1226 (
1227 cd simple_${sideL}_${sideR} &&
1228
1229 git checkout L^0 &&
1230
1231 # Merge must fail; there is a conflict
1232 test_must_fail git merge -s recursive R^0 &&
1233
1234 # Make sure the index has the right number of entries
1235 git ls-files -s >out &&
1236 test_line_count = 3 out &&
1237 git ls-files -u >out &&
1238 test_line_count = 2 out &&
1239 # Ensure we have the correct number of untracked files
1240 git ls-files -o >out &&
1241 test_line_count = 1 out &&
1242
1243 # Nothing should have touched irrelevant_file
1244 git rev-parse >actual \
1245 :0:irrelevant_file \
1246 :2:three \
1247 :3:three &&
1248 git rev-parse >expected \
1249 master:irrelevant_file \
1250 file_v2 \
1251 file_v4 &&
1252 test_cmp expected actual &&
1253
1254 # Make sure we have the correct merged contents for
1255 # three
1256 git show file_v1 >expected &&
1257 cat <<-\EOF >>expected &&
1258 <<<<<<< HEAD
1259 modification
1260 =======
1261 more stuff
1262 yet more stuff
1263 >>>>>>> R^0
1264 EOF
1265
1266 test_cmp expected three
1267 )
1268 '
1269 }
1270
1271 test_conflicts_with_adds_and_renames rename rename
1272 test_conflicts_with_adds_and_renames rename add
1273 test_conflicts_with_adds_and_renames add rename
1274 test_conflicts_with_adds_and_renames add add
1275
1276 # Setup:
1277 # L
1278 # / \
1279 # master ?
1280 # \ /
1281 # R
1282 #
1283 # Where:
1284 # master has two files, named 'one' and 'two'.
1285 # branches L and R both modify 'one', in conflicting ways.
1286 # branches L and R both modify 'two', in conflicting ways.
1287 # branch L also renames 'one' to 'three'.
1288 # branch R also renames 'two' to 'three'.
1289 #
1290 # So, we have four different conflicting files that all end up at path
1291 # 'three'.
1292 test_setup_nested_conflicts_from_rename_rename () {
1293 test_create_repo nested_conflicts_from_rename_rename &&
1294 (
1295 cd nested_conflicts_from_rename_rename &&
1296
1297 # Create some related files now
1298 for i in $(test_seq 1 10)
1299 do
1300 echo Random base content line $i
1301 done >file_v1 &&
1302
1303 cp file_v1 file_v2 &&
1304 cp file_v1 file_v3 &&
1305 cp file_v1 file_v4 &&
1306 cp file_v1 file_v5 &&
1307 cp file_v1 file_v6 &&
1308
1309 echo one >>file_v1 &&
1310 echo uno >>file_v2 &&
1311 echo eins >>file_v3 &&
1312
1313 echo two >>file_v4 &&
1314 echo dos >>file_v5 &&
1315 echo zwei >>file_v6 &&
1316
1317 # Setup original commit (or merge-base), consisting of
1318 # files named "one" and "two".
1319 mv file_v1 one &&
1320 mv file_v4 two &&
1321 git add one two &&
1322 test_tick && git commit -m english &&
1323
1324 git branch L &&
1325 git branch R &&
1326
1327 # Handle the left side
1328 git checkout L &&
1329 git rm one two &&
1330 mv -f file_v2 three &&
1331 mv -f file_v5 two &&
1332 git add two three &&
1333 test_tick && git commit -m spanish &&
1334
1335 # Handle the right side
1336 git checkout R &&
1337 git rm one two &&
1338 mv -f file_v3 one &&
1339 mv -f file_v6 three &&
1340 git add one three &&
1341 test_tick && git commit -m german
1342 )
1343 }
1344
1345 test_expect_success 'check nested conflicts from rename/rename(2to1)' '
1346 test_setup_nested_conflicts_from_rename_rename &&
1347 (
1348 cd nested_conflicts_from_rename_rename &&
1349
1350 git checkout L^0 &&
1351
1352 # Merge must fail; there is a conflict
1353 test_must_fail git merge -s recursive R^0 &&
1354
1355 # Make sure the index has the right number of entries
1356 git ls-files -s >out &&
1357 test_line_count = 2 out &&
1358 git ls-files -u >out &&
1359 test_line_count = 2 out &&
1360 # Ensure we have the correct number of untracked files
1361 git ls-files -o >out &&
1362 test_line_count = 1 out &&
1363
1364 # Compare :2:three to expected values
1365 git cat-file -p master:one >base &&
1366 git cat-file -p L:three >ours &&
1367 git cat-file -p R:one >theirs &&
1368 test_must_fail git merge-file \
1369 -L "HEAD:three" -L "" -L "R^0:one" \
1370 ours base theirs &&
1371 sed -e "s/^\([<=>]\)/\1\1/" ours >L-three &&
1372 git cat-file -p :2:three >expect &&
1373 test_cmp expect L-three &&
1374
1375 # Compare :2:three to expected values
1376 git cat-file -p master:two >base &&
1377 git cat-file -p L:two >ours &&
1378 git cat-file -p R:three >theirs &&
1379 test_must_fail git merge-file \
1380 -L "HEAD:two" -L "" -L "R^0:three" \
1381 ours base theirs &&
1382 sed -e "s/^\([<=>]\)/\1\1/" ours >R-three &&
1383 git cat-file -p :3:three >expect &&
1384 test_cmp expect R-three &&
1385
1386 # Compare three to expected contents
1387 >empty &&
1388 test_must_fail git merge-file \
1389 -L "HEAD" -L "" -L "R^0" \
1390 L-three empty R-three &&
1391 test_cmp three L-three
1392 )
1393 '
1394
1395 # Testcase rename/rename(1to2) of a binary file
1396 # Commit O: orig
1397 # Commit A: orig-A
1398 # Commit B: orig-B
1399 # Expected: CONFLICT(rename/rename) message, three unstaged entries in the
1400 # index, and contents of orig-[AB] at path orig-[AB]
1401 test_setup_rename_rename_1_to_2_binary () {
1402 test_create_repo rename_rename_1_to_2_binary &&
1403 (
1404 cd rename_rename_1_to_2_binary &&
1405
1406 echo '* binary' >.gitattributes &&
1407 git add .gitattributes &&
1408
1409 test_seq 1 10 >orig &&
1410 git add orig &&
1411 git commit -m orig &&
1412
1413 git branch A &&
1414 git branch B &&
1415
1416 git checkout A &&
1417 git mv orig orig-A &&
1418 test_seq 1 11 >orig-A &&
1419 git add orig-A &&
1420 git commit -m orig-A &&
1421
1422 git checkout B &&
1423 git mv orig orig-B &&
1424 test_seq 0 10 >orig-B &&
1425 git add orig-B &&
1426 git commit -m orig-B
1427
1428 )
1429 }
1430
1431 test_expect_success 'rename/rename(1to2) with a binary file' '
1432 test_setup_rename_rename_1_to_2_binary &&
1433 (
1434 cd rename_rename_1_to_2_binary &&
1435
1436 git checkout A^0 &&
1437
1438 test_must_fail git merge -s recursive B^0 &&
1439
1440 # Make sure the index has the right number of entries
1441 git ls-files -s >actual &&
1442 test_line_count = 4 actual &&
1443
1444 git rev-parse A:orig-A B:orig-B >expect &&
1445 git hash-object orig-A orig-B >actual &&
1446 test_cmp expect actual
1447 )
1448 '
1449
1450 test_done