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