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