t6423, t6436: note improved ort handling with dirty files
[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