Merge branch 'ag/edit-todo-drop-check'
[git] / t / t6036-recursive-corner-cases.sh
1 #!/bin/sh
2
3 test_description='recursive merge corner cases involving criss-cross merges'
4
5 . ./test-lib.sh
6
7 #
8 #  L1  L2
9 #   o---o
10 #  / \ / \
11 # o   X   ?
12 #  \ / \ /
13 #   o---o
14 #  R1  R2
15 #
16
17 test_expect_success 'setup basic criss-cross + rename with no modifications' '
18         test_create_repo basic-rename &&
19         (
20                 cd basic-rename &&
21
22                 ten="0 1 2 3 4 5 6 7 8 9" &&
23                 for i in $ten
24                 do
25                         echo line $i in a sample file
26                 done >one &&
27                 for i in $ten
28                 do
29                         echo line $i in another sample file
30                 done >two &&
31                 git add one two &&
32                 test_tick && git commit -m initial &&
33
34                 git branch L1 &&
35                 git checkout -b R1 &&
36                 git mv one three &&
37                 test_tick && git commit -m R1 &&
38
39                 git checkout L1 &&
40                 git mv two three &&
41                 test_tick && git commit -m L1 &&
42
43                 git checkout L1^0 &&
44                 test_tick && git merge -s ours R1 &&
45                 git tag L2 &&
46
47                 git checkout R1^0 &&
48                 test_tick && git merge -s ours L1 &&
49                 git tag R2
50         )
51 '
52
53 test_expect_success 'merge simple rename+criss-cross with no modifications' '
54         (
55                 cd basic-rename &&
56
57                 git reset --hard &&
58                 git checkout L2^0 &&
59
60                 test_must_fail git merge -s recursive R2^0 &&
61
62                 git ls-files -s >out &&
63                 test_line_count = 2 out &&
64                 git ls-files -u >out &&
65                 test_line_count = 2 out &&
66                 git ls-files -o >out &&
67                 test_line_count = 1 out &&
68
69                 git rev-parse >expect       \
70                         L2:three   R2:three &&
71                 git rev-parse   >actual     \
72                         :2:three   :3:three &&
73                 test_cmp expect actual
74         )
75 '
76
77 #
78 # Same as before, but modify L1 slightly:
79 #
80 #  L1m L2
81 #   o---o
82 #  / \ / \
83 # o   X   ?
84 #  \ / \ /
85 #   o---o
86 #  R1  R2
87 #
88
89 test_expect_success 'setup criss-cross + rename merges with basic modification' '
90         test_create_repo rename-modify &&
91         (
92                 cd rename-modify &&
93
94                 ten="0 1 2 3 4 5 6 7 8 9" &&
95                 for i in $ten
96                 do
97                         echo line $i in a sample file
98                 done >one &&
99                 for i in $ten
100                 do
101                         echo line $i in another sample file
102                 done >two &&
103                 git add one two &&
104                 test_tick && git commit -m initial &&
105
106                 git branch L1 &&
107                 git checkout -b R1 &&
108                 git mv one three &&
109                 echo more >>two &&
110                 git add two &&
111                 test_tick && git commit -m R1 &&
112
113                 git checkout L1 &&
114                 git mv two three &&
115                 test_tick && git commit -m L1 &&
116
117                 git checkout L1^0 &&
118                 test_tick && git merge -s ours R1 &&
119                 git tag L2 &&
120
121                 git checkout R1^0 &&
122                 test_tick && git merge -s ours L1 &&
123                 git tag R2
124         )
125 '
126
127 test_expect_success 'merge criss-cross + rename merges with basic modification' '
128         (
129                 cd rename-modify &&
130
131                 git checkout L2^0 &&
132
133                 test_must_fail git merge -s recursive R2^0 &&
134
135                 git ls-files -s >out &&
136                 test_line_count = 2 out &&
137                 git ls-files -u >out &&
138                 test_line_count = 2 out &&
139                 git ls-files -o >out &&
140                 test_line_count = 1 out &&
141
142                 git rev-parse >expect       \
143                         L2:three   R2:three &&
144                 git rev-parse   >actual     \
145                         :2:three   :3:three &&
146                 test_cmp expect actual
147         )
148 '
149
150 #
151 # For the next test, we start with three commits in two lines of development
152 # which setup a rename/add conflict:
153 #   Commit A: File 'a' exists
154 #   Commit B: Rename 'a' -> 'new_a'
155 #   Commit C: Modify 'a', create different 'new_a'
156 # Later, two different people merge and resolve differently:
157 #   Commit D: Merge B & C, ignoring separately created 'new_a'
158 #   Commit E: Merge B & C making use of some piece of secondary 'new_a'
159 # Finally, someone goes to merge D & E.  Does git detect the conflict?
160 #
161 #      B   D
162 #      o---o
163 #     / \ / \
164 #  A o   X   ? F
165 #     \ / \ /
166 #      o---o
167 #      C   E
168 #
169
170 test_expect_success 'setup differently handled merges of rename/add conflict' '
171         test_create_repo rename-add &&
172         (
173                 cd rename-add &&
174
175                 printf "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n" >a &&
176                 git add a &&
177                 test_tick && git commit -m A &&
178
179                 git branch B &&
180                 git checkout -b C &&
181                 echo 10 >>a &&
182                 test_write_lines 0 1 2 3 4 5 6 7 foobar >new_a &&
183                 git add a new_a &&
184                 test_tick && git commit -m C &&
185
186                 git checkout B &&
187                 git mv a new_a &&
188                 test_tick && git commit -m B &&
189
190                 git checkout B^0 &&
191                 test_must_fail git merge C &&
192                 git show :2:new_a >new_a &&
193                 git add new_a &&
194                 test_tick && git commit -m D &&
195                 git tag D &&
196
197                 git checkout C^0 &&
198                 test_must_fail git merge B &&
199                 test_write_lines 0 1 2 3 4 5 6 7 bad_merge >new_a &&
200                 git add -u &&
201                 test_tick && git commit -m E &&
202                 git tag E
203         )
204 '
205
206 test_expect_success 'git detects differently handled merges conflict' '
207         (
208                 cd rename-add &&
209
210                 git checkout D^0 &&
211
212                 test_must_fail git merge -s recursive E^0 &&
213
214                 git ls-files -s >out &&
215                 test_line_count = 3 out &&
216                 git ls-files -u >out &&
217                 test_line_count = 3 out &&
218                 git ls-files -o >out &&
219                 test_line_count = 1 out &&
220
221                 git rev-parse >expect       \
222                         C:new_a  D:new_a  E:new_a &&
223                 git rev-parse   >actual     \
224                         :1:new_a :2:new_a :3:new_a &&
225                 test_cmp expect actual &&
226
227                 # Test that the two-way merge in new_a is as expected
228                 git cat-file -p D:new_a >ours &&
229                 git cat-file -p E:new_a >theirs &&
230                 >empty &&
231                 test_must_fail git merge-file \
232                         -L "HEAD" \
233                         -L "" \
234                         -L "E^0" \
235                         ours empty theirs &&
236                 sed -e "s/^\([<=>]\)/\1\1\1/" ours >expect &&
237                 git hash-object new_a >actual &&
238                 git hash-object ours  >expect &&
239                 test_cmp expect actual
240         )
241 '
242
243 # Repeat the above testcase with precisely the same setup, other than with
244 # the two merge bases having different orderings of commit timestamps so
245 # that they are reversed in the order they are provided to merge-recursive,
246 # so that we can improve code coverage.
247 test_expect_success 'git detects differently handled merges conflict, swapped' '
248         (
249                 cd rename-add &&
250
251                 # Difference #1: Do cleanup from previous testrun
252                 git reset --hard &&
253                 git clean -fdqx &&
254
255                 # Difference #2: Change commit timestamps
256                 btime=$(git log --no-walk --date=raw --format=%cd B | awk "{print \$1}") &&
257                 ctime=$(git log --no-walk --date=raw --format=%cd C | awk "{print \$1}") &&
258                 newctime=$(($btime+1)) &&
259                 git fast-export --no-data --all | sed -e s/$ctime/$newctime/ | git fast-import --force --quiet &&
260                 # End of differences; rest is copy-paste of last test
261
262                 git checkout D^0 &&
263                 test_must_fail git merge -s recursive E^0 &&
264
265                 git ls-files -s >out &&
266                 test_line_count = 3 out &&
267                 git ls-files -u >out &&
268                 test_line_count = 3 out &&
269                 git ls-files -o >out &&
270                 test_line_count = 1 out &&
271
272                 git rev-parse >expect       \
273                         C:new_a  D:new_a  E:new_a &&
274                 git rev-parse   >actual     \
275                         :1:new_a :2:new_a :3:new_a &&
276                 test_cmp expect actual &&
277
278                 # Test that the two-way merge in new_a is as expected
279                 git cat-file -p D:new_a >ours &&
280                 git cat-file -p E:new_a >theirs &&
281                 >empty &&
282                 test_must_fail git merge-file \
283                         -L "HEAD" \
284                         -L "" \
285                         -L "E^0" \
286                         ours empty theirs &&
287                 sed -e "s/^\([<=>]\)/\1\1\1/" ours >expect &&
288                 git hash-object new_a >actual &&
289                 git hash-object ours  >expect &&
290                 test_cmp expect actual
291         )
292 '
293
294 #
295 # criss-cross + modify/delete:
296 #
297 #      B   D
298 #      o---o
299 #     / \ / \
300 #  A o   X   ? F
301 #     \ / \ /
302 #      o---o
303 #      C   E
304 #
305 #   Commit A: file with contents 'A\n'
306 #   Commit B: file with contents 'B\n'
307 #   Commit C: file not present
308 #   Commit D: file with contents 'B\n'
309 #   Commit E: file not present
310 #
311 # Merging commits D & E should result in modify/delete conflict.
312
313 test_expect_success 'setup criss-cross + modify/delete resolved differently' '
314         test_create_repo modify-delete &&
315         (
316                 cd modify-delete &&
317
318                 echo A >file &&
319                 git add file &&
320                 test_tick &&
321                 git commit -m A &&
322
323                 git branch B &&
324                 git checkout -b C &&
325                 git rm file &&
326                 test_tick &&
327                 git commit -m C &&
328
329                 git checkout B &&
330                 echo B >file &&
331                 git add file &&
332                 test_tick &&
333                 git commit -m B &&
334
335                 git checkout B^0 &&
336                 test_must_fail git merge C &&
337                 echo B >file &&
338                 git add file &&
339                 test_tick &&
340                 git commit -m D &&
341                 git tag D &&
342
343                 git checkout C^0 &&
344                 test_must_fail git merge B &&
345                 git rm file &&
346                 test_tick &&
347                 git commit -m E &&
348                 git tag E
349         )
350 '
351
352 test_expect_success 'git detects conflict merging criss-cross+modify/delete' '
353         (
354                 cd modify-delete &&
355
356                 git checkout D^0 &&
357
358                 test_must_fail git merge -s recursive E^0 &&
359
360                 git ls-files -s >out &&
361                 test_line_count = 2 out &&
362                 git ls-files -u >out &&
363                 test_line_count = 2 out &&
364
365                 git rev-parse >expect       \
366                         master:file  B:file &&
367                 git rev-parse   >actual      \
368                         :1:file      :2:file &&
369                 test_cmp expect actual
370         )
371 '
372
373 test_expect_success 'git detects conflict merging criss-cross+modify/delete, reverse direction' '
374         (
375                 cd modify-delete &&
376
377                 git reset --hard &&
378                 git checkout E^0 &&
379
380                 test_must_fail git merge -s recursive D^0 &&
381
382                 git ls-files -s >out &&
383                 test_line_count = 2 out &&
384                 git ls-files -u >out &&
385                 test_line_count = 2 out &&
386
387                 git rev-parse >expect       \
388                         master:file  B:file &&
389                 git rev-parse   >actual      \
390                         :1:file      :3:file &&
391                 test_cmp expect actual
392         )
393 '
394
395 #      SORRY FOR THE SUPER LONG DESCRIPTION, BUT THIS NEXT ONE IS HAIRY
396 #
397 # criss-cross + d/f conflict via add/add:
398 #   Commit A: Neither file 'a' nor directory 'a/' exists.
399 #   Commit B: Introduce 'a'
400 #   Commit C: Introduce 'a/file'
401 #   Commit D1: Merge B & C, keeping 'a'    and deleting 'a/'
402 #   Commit E1: Merge B & C, deleting 'a' but keeping 'a/file'
403 #
404 #      B   D1 or D2
405 #      o---o
406 #     / \ / \
407 #  A o   X   ? F
408 #     \ / \ /
409 #      o---o
410 #      C   E1 or E2 or E3
411 #
412 # I'll describe D2, E2, & E3 (which are alternatives for D1 & E1) more below...
413 #
414 # Merging D1 & E1 requires we first create a virtual merge base X from
415 # merging A & B in memory.  There are several possibilities for the merge-base:
416 #   1: Keep both 'a' and 'a/file' (assuming crazy filesystem allowing a tree
417 #      with a directory and file at same path): results in merge of D1 & E1
418 #      being clean with both files deleted.  Bad (no conflict detected).
419 #   2: Keep 'a' but not 'a/file': Merging D1 & E1 is clean and matches E1.  Bad.
420 #   3: Keep 'a/file' but not 'a': Merging D1 & E1 is clean and matches D1.  Bad.
421 #   4: Keep neither file: Merging D1 & E1 reports the D/F add/add conflict.
422 #
423 # So 4 sounds good for this case, but if we were to merge D1 & E3, where E3
424 # is defined as:
425 #   Commit E3: Merge B & C, keeping modified a, and deleting a/
426 # then we'd get an add/add conflict for 'a', which seems suboptimal.  A little
427 # creativity leads us to an alternate choice:
428 #   5: Keep 'a' as 'a~$UNIQUE' and a/file; results:
429 #        Merge D1 & E1: rename/delete conflict for 'a'; a/file silently deleted
430 #        Merge D1 & E3 is clean, as expected.
431 #
432 # So choice 5 at least provides some kind of conflict for the original case,
433 # and can merge cleanly as expected with D1 and E3.  It also made things just
434 # slightly funny for merging D1 and e$, where E4 is defined as:
435 #   Commit E4: Merge B & C, modifying 'a' and renaming to 'a2', and deleting 'a/'
436 # in this case, we'll get a rename/rename(1to2) conflict because a~$UNIQUE
437 # gets renamed to 'a' in D1 and to 'a2' in E4.  But that's better than having
438 # two files (both 'a' and 'a2') sitting around without the user being notified
439 # that we could detect they were related and need to be merged.  Also, choice
440 # 5 makes the handling of 'a/file' seem suboptimal.  What if we were to merge
441 # D2 and E4, where D2 is:
442 #   Commit D2: Merge B & C, renaming 'a'->'a2', keeping 'a/file'
443 # This would result in a clean merge with 'a2' having three-way merged
444 # contents (good), and deleting 'a/' (bad) -- it doesn't detect the
445 # conflict in how the different sides treated a/file differently.
446 # Continuing down the creative route:
447 #   6: Keep 'a' as 'a~$UNIQUE1' and keep 'a/' as 'a~$UNIQUE2/'; results:
448 #        Merge D1 & E1: rename/delete conflict for 'a' and each path under 'a/'.
449 #        Merge D1 & E3: clean, as expected.
450 #        Merge D1 & E4: rename/rename(1to2) conflict on 'a' vs 'a2'.
451 #        Merge D2 & E4: clean for 'a2', rename/delete for a/file
452 #
453 # Choice 6 could cause rename detection to take longer (providing more targets
454 # that need to be searched).  Also, the conflict message for each path under
455 # 'a/' might be annoying unless we can detect it at the directory level, print
456 # it once, and then suppress it for individual filepaths underneath.
457 #
458 #
459 # As of time of writing, git uses choice 5.  Directory rename detection and
460 # rename detection performance improvements might make choice 6 a desirable
461 # improvement.  But we can at least document where we fall short for now...
462 #
463 #
464 # Historically, this testcase also used:
465 #   Commit E2: Merge B & C, deleting 'a' but keeping slightly modified 'a/file'
466 # The merge of D1 & E2 is very similar to D1 & E1 -- it has similar issues for
467 # path 'a', but should always result in a modify/delete conflict for path
468 # 'a/file'.  These tests ran the two merges
469 #   D1 & E1
470 #   D1 & E2
471 # in both directions, to check for directional issues with D/F conflict
472 # handling. Later we added
473 #   D1 & E3
474 #   D1 & E4
475 #   D2 & E4
476 # for good measure, though we only ran those one way because we had pretty
477 # good confidence in merge-recursive's directional handling of D/F issues.
478 #
479 # Just to summarize all the intermediate merge commits:
480 #   Commit D1: Merge B & C, keeping a    and deleting a/
481 #   Commit D2: Merge B & C, renaming a->a2, keeping a/file
482 #   Commit E1: Merge B & C, deleting a but keeping a/file
483 #   Commit E2: Merge B & C, deleting a but keeping slightly modified a/file
484 #   Commit E3: Merge B & C, keeping modified a, and deleting a/
485 #   Commit E4: Merge B & C, modifying 'a' and renaming to 'a2', and deleting 'a/'
486 #
487
488 test_expect_success 'setup differently handled merges of directory/file conflict' '
489         test_create_repo directory-file &&
490         (
491                 cd directory-file &&
492
493                 >ignore-me &&
494                 git add ignore-me &&
495                 test_tick &&
496                 git commit -m A &&
497                 git tag A &&
498
499                 git branch B &&
500                 git checkout -b C &&
501                 mkdir a &&
502                 test_write_lines a b c d e f g >a/file &&
503                 git add a/file &&
504                 test_tick &&
505                 git commit -m C &&
506
507                 git checkout B &&
508                 test_write_lines 1 2 3 4 5 6 7 >a &&
509                 git add a &&
510                 test_tick &&
511                 git commit -m B &&
512
513                 git checkout B^0 &&
514                 git merge -s ours -m D1 C^0 &&
515                 git tag D1 &&
516
517                 git checkout B^0 &&
518                 test_must_fail git merge C^0 &&
519                 git clean -fd &&
520                 git rm -rf a/ &&
521                 git rm a &&
522                 git cat-file -p B:a >a2 &&
523                 git add a2 &&
524                 git commit -m D2 &&
525                 git tag D2 &&
526
527                 git checkout C^0 &&
528                 git merge -s ours -m E1 B^0 &&
529                 git tag E1 &&
530
531                 git checkout C^0 &&
532                 git merge -s ours -m E2 B^0 &&
533                 test_write_lines a b c d e f g h >a/file &&
534                 git add a/file &&
535                 git commit --amend -C HEAD &&
536                 git tag E2 &&
537
538                 git checkout C^0 &&
539                 test_must_fail git merge B^0 &&
540                 git clean -fd &&
541                 git rm -rf a/ &&
542                 test_write_lines 1 2 3 4 5 6 7 8 >a &&
543                 git add a &&
544                 git commit -m E3 &&
545                 git tag E3 &&
546
547                 git checkout C^0 &&
548                 test_must_fail git merge B^0 &&
549                 git clean -fd &&
550                 git rm -rf a/ &&
551                 git rm a &&
552                 test_write_lines 1 2 3 4 5 6 7 8 >a2 &&
553                 git add a2 &&
554                 git commit -m E4 &&
555                 git tag E4
556         )
557 '
558
559 test_expect_success 'merge of D1 & E1 fails but has appropriate contents' '
560         test_when_finished "git -C directory-file reset --hard" &&
561         test_when_finished "git -C directory-file clean -fdqx" &&
562         (
563                 cd directory-file &&
564
565                 git checkout D1^0 &&
566
567                 test_must_fail git merge -s recursive E1^0 &&
568
569                 git ls-files -s >out &&
570                 test_line_count = 2 out &&
571                 git ls-files -u >out &&
572                 test_line_count = 1 out &&
573                 git ls-files -o >out &&
574                 test_line_count = 1 out &&
575
576                 git rev-parse >expect    \
577                         A:ignore-me  B:a &&
578                 git rev-parse   >actual   \
579                         :0:ignore-me :2:a &&
580                 test_cmp expect actual
581         )
582 '
583
584 test_expect_success 'merge of E1 & D1 fails but has appropriate contents' '
585         test_when_finished "git -C directory-file reset --hard" &&
586         test_when_finished "git -C directory-file clean -fdqx" &&
587         (
588                 cd directory-file &&
589
590                 git checkout E1^0 &&
591
592                 test_must_fail git merge -s recursive D1^0 &&
593
594                 git ls-files -s >out &&
595                 test_line_count = 2 out &&
596                 git ls-files -u >out &&
597                 test_line_count = 1 out &&
598                 git ls-files -o >out &&
599                 test_line_count = 1 out &&
600
601                 git rev-parse >expect    \
602                         A:ignore-me  B:a &&
603                 git rev-parse   >actual   \
604                         :0:ignore-me :3:a &&
605                 test_cmp expect actual
606         )
607 '
608
609 test_expect_success 'merge of D1 & E2 fails but has appropriate contents' '
610         test_when_finished "git -C directory-file reset --hard" &&
611         test_when_finished "git -C directory-file clean -fdqx" &&
612         (
613                 cd directory-file &&
614
615                 git checkout D1^0 &&
616
617                 test_must_fail git merge -s recursive E2^0 &&
618
619                 git ls-files -s >out &&
620                 test_line_count = 4 out &&
621                 git ls-files -u >out &&
622                 test_line_count = 3 out &&
623                 git ls-files -o >out &&
624                 test_line_count = 2 out &&
625
626                 git rev-parse >expect    \
627                         B:a   E2:a/file  C:a/file   A:ignore-me &&
628                 git rev-parse   >actual   \
629                         :2:a  :3:a/file  :1:a/file  :0:ignore-me &&
630                 test_cmp expect actual &&
631
632                 test_path_is_file a~HEAD
633         )
634 '
635
636 test_expect_success 'merge of E2 & D1 fails but has appropriate contents' '
637         test_when_finished "git -C directory-file reset --hard" &&
638         test_when_finished "git -C directory-file clean -fdqx" &&
639         (
640                 cd directory-file &&
641
642                 git checkout E2^0 &&
643
644                 test_must_fail git merge -s recursive D1^0 &&
645
646                 git ls-files -s >out &&
647                 test_line_count = 4 out &&
648                 git ls-files -u >out &&
649                 test_line_count = 3 out &&
650                 git ls-files -o >out &&
651                 test_line_count = 2 out &&
652
653                 git rev-parse >expect    \
654                         B:a   E2:a/file  C:a/file   A:ignore-me &&
655                 git rev-parse   >actual   \
656                         :3:a  :2:a/file  :1:a/file  :0:ignore-me &&
657                 test_cmp expect actual &&
658
659                 test_path_is_file a~D1^0
660         )
661 '
662
663 test_expect_success 'merge of D1 & E3 succeeds' '
664         test_when_finished "git -C directory-file reset --hard" &&
665         test_when_finished "git -C directory-file clean -fdqx" &&
666         (
667                 cd directory-file &&
668
669                 git checkout D1^0 &&
670
671                 git merge -s recursive E3^0 &&
672
673                 git ls-files -s >out &&
674                 test_line_count = 2 out &&
675                 git ls-files -u >out &&
676                 test_line_count = 0 out &&
677                 git ls-files -o >out &&
678                 test_line_count = 1 out &&
679
680                 git rev-parse >expect    \
681                         A:ignore-me  E3:a &&
682                 git rev-parse   >actual   \
683                         :0:ignore-me :0:a &&
684                 test_cmp expect actual
685         )
686 '
687
688 test_expect_success 'merge of D1 & E4 notifies user a and a2 are related' '
689         test_when_finished "git -C directory-file reset --hard" &&
690         test_when_finished "git -C directory-file clean -fdqx" &&
691         (
692                 cd directory-file &&
693
694                 git checkout D1^0 &&
695
696                 test_must_fail git merge -s recursive E4^0 &&
697
698                 git ls-files -s >out &&
699                 test_line_count = 4 out &&
700                 git ls-files -u >out &&
701                 test_line_count = 3 out &&
702                 git ls-files -o >out &&
703                 test_line_count = 1 out &&
704
705                 git rev-parse >expect                  \
706                         A:ignore-me  B:a   D1:a  E4:a2 &&
707                 git rev-parse   >actual                \
708                         :0:ignore-me :1:a~Temporary\ merge\ branch\ 2  :2:a  :3:a2 &&
709                 test_cmp expect actual
710         )
711 '
712
713 test_expect_failure 'merge of D2 & E4 merges a2s & reports conflict for a/file' '
714         test_when_finished "git -C directory-file reset --hard" &&
715         test_when_finished "git -C directory-file clean -fdqx" &&
716         (
717                 cd directory-file &&
718
719                 git checkout D2^0 &&
720
721                 test_must_fail git merge -s recursive E4^0 &&
722
723                 git ls-files -s >out &&
724                 test_line_count = 3 out &&
725                 git ls-files -u >out &&
726                 test_line_count = 1 out &&
727                 git ls-files -o >out &&
728                 test_line_count = 1 out &&
729
730                 git rev-parse >expect                 \
731                         A:ignore-me  E4:a2  D2:a/file &&
732                 git rev-parse   >actual               \
733                         :0:ignore-me :0:a2  :2:a/file &&
734                 test_cmp expect actual
735         )
736 '
737
738 #
739 # criss-cross with rename/rename(1to2)/modify followed by
740 # rename/rename(2to1)/modify:
741 #
742 #      B   D
743 #      o---o
744 #     / \ / \
745 #  A o   X   ? F
746 #     \ / \ /
747 #      o---o
748 #      C   E
749 #
750 #   Commit A: new file: a
751 #   Commit B: rename a->b, modifying by adding a line
752 #   Commit C: rename a->c
753 #   Commit D: merge B&C, resolving conflict by keeping contents in newname
754 #   Commit E: merge B&C, resolving conflict similar to D but adding another line
755 #
756 # There is a conflict merging B & C, but one of filename not of file
757 # content.  Whoever created D and E chose specific resolutions for that
758 # conflict resolution.  Now, since: (1) there is no content conflict
759 # merging B & C, (2) D does not modify that merged content further, and (3)
760 # both D & E resolve the name conflict in the same way, the modification to
761 # newname in E should not cause any conflicts when it is merged with D.
762 # (Note that this can be accomplished by having the virtual merge base have
763 # the merged contents of b and c stored in a file named a, which seems like
764 # the most logical choice anyway.)
765 #
766 # Comment from Junio: I do not necessarily agree with the choice "a", but
767 # it feels sound to say "B and C do not agree what the final pathname
768 # should be, but we know this content was derived from the common A:a so we
769 # use one path whose name is arbitrary in the virtual merge base X between
770 # D and E" and then further let the rename detection to notice that that
771 # arbitrary path gets renamed between X-D to "newname" and X-E also to
772 # "newname" to resolve it as both sides renaming it to the same new
773 # name. It is akin to what we do at the content level, i.e. "B and C do not
774 # agree what the final contents should be, so we leave the conflict marker
775 # but that may cancel out at the final merge stage".
776
777 test_expect_success 'setup rename/rename(1to2)/modify followed by what looks like rename/rename(2to1)/modify' '
778         test_create_repo rename-squared-squared &&
779         (
780                 cd rename-squared-squared &&
781
782                 printf "1\n2\n3\n4\n5\n6\n" >a &&
783                 git add a &&
784                 git commit -m A &&
785                 git tag A &&
786
787                 git checkout -b B A &&
788                 git mv a b &&
789                 echo 7 >>b &&
790                 git add -u &&
791                 git commit -m B &&
792
793                 git checkout -b C A &&
794                 git mv a c &&
795                 git commit -m C &&
796
797                 git checkout -q B^0 &&
798                 git merge --no-commit -s ours C^0 &&
799                 git mv b newname &&
800                 git commit -m "Merge commit C^0 into HEAD" &&
801                 git tag D &&
802
803                 git checkout -q C^0 &&
804                 git merge --no-commit -s ours B^0 &&
805                 git mv c newname &&
806                 printf "7\n8\n" >>newname &&
807                 git add -u &&
808                 git commit -m "Merge commit B^0 into HEAD" &&
809                 git tag E
810         )
811 '
812
813 test_expect_success 'handle rename/rename(1to2)/modify followed by what looks like rename/rename(2to1)/modify' '
814         (
815                 cd rename-squared-squared &&
816
817                 git checkout D^0 &&
818
819                 git merge -s recursive E^0 &&
820
821                 git ls-files -s >out &&
822                 test_line_count = 1 out &&
823                 git ls-files -u >out &&
824                 test_line_count = 0 out &&
825                 git ls-files -o >out &&
826                 test_line_count = 1 out &&
827
828                 test $(git rev-parse HEAD:newname) = $(git rev-parse E:newname)
829         )
830 '
831
832 #
833 # criss-cross with rename/rename(1to2)/add-source + resolvable modify/modify:
834 #
835 #      B   D
836 #      o---o
837 #     / \ / \
838 #  A o   X   ? F
839 #     \ / \ /
840 #      o---o
841 #      C   E
842 #
843 #   Commit A: new file: a
844 #   Commit B: rename a->b
845 #   Commit C: rename a->c, add different a
846 #   Commit D: merge B&C, keeping b&c and (new) a modified at beginning
847 #   Commit E: merge B&C, keeping b&c and (new) a modified at end
848 #
849 # Merging commits D & E should result in no conflict; doing so correctly
850 # requires getting the virtual merge base (from merging B&C) right, handling
851 # renaming carefully (both in the virtual merge base and later), and getting
852 # content merge handled.
853
854 test_expect_success 'setup criss-cross + rename/rename/add-source + modify/modify' '
855         test_create_repo rename-rename-add-source &&
856         (
857                 cd rename-rename-add-source &&
858
859                 printf "lots\nof\nwords\nand\ncontent\n" >a &&
860                 git add a &&
861                 git commit -m A &&
862                 git tag A &&
863
864                 git checkout -b B A &&
865                 git mv a b &&
866                 git commit -m B &&
867
868                 git checkout -b C A &&
869                 git mv a c &&
870                 printf "2\n3\n4\n5\n6\n7\n" >a &&
871                 git add a &&
872                 git commit -m C &&
873
874                 git checkout B^0 &&
875                 git merge --no-commit -s ours C^0 &&
876                 git checkout C -- a c &&
877                 mv a old_a &&
878                 echo 1 >a &&
879                 cat old_a >>a &&
880                 rm old_a &&
881                 git add -u &&
882                 git commit -m "Merge commit C^0 into HEAD" &&
883                 git tag D &&
884
885                 git checkout C^0 &&
886                 git merge --no-commit -s ours B^0 &&
887                 git checkout B -- b &&
888                 echo 8 >>a &&
889                 git add -u &&
890                 git commit -m "Merge commit B^0 into HEAD" &&
891                 git tag E
892         )
893 '
894
895 test_expect_failure 'detect rename/rename/add-source for virtual merge-base' '
896         (
897                 cd rename-rename-add-source &&
898
899                 git checkout D^0 &&
900
901                 git merge -s recursive E^0 &&
902
903                 git ls-files -s >out &&
904                 test_line_count = 3 out &&
905                 git ls-files -u >out &&
906                 test_line_count = 0 out &&
907                 git ls-files -o >out &&
908                 test_line_count = 1 out &&
909
910                 printf "1\n2\n3\n4\n5\n6\n7\n8\n" >correct &&
911                 git rev-parse >expect \
912                         A:a   A:a     \
913                         correct       &&
914                 git rev-parse   >actual  \
915                         :0:b  :0:c       &&
916                 git hash-object >>actual \
917                         a                &&
918                 test_cmp expect actual
919         )
920 '
921
922 #
923 # criss-cross with rename/rename(1to2)/add-dest + simple modify:
924 #
925 #      B   D
926 #      o---o
927 #     / \ / \
928 #  A o   X   ? F
929 #     \ / \ /
930 #      o---o
931 #      C   E
932 #
933 #   Commit A: new file: a
934 #   Commit B: rename a->b, add c
935 #   Commit C: rename a->c
936 #   Commit D: merge B&C, keeping A:a and B:c
937 #   Commit E: merge B&C, keeping A:a and slightly modified c from B
938 #
939 # Merging commits D & E should result in no conflict.  The virtual merge
940 # base of B & C needs to not delete B:c for that to work, though...
941
942 test_expect_success 'setup criss-cross+rename/rename/add-dest + simple modify' '
943         test_create_repo rename-rename-add-dest &&
944         (
945                 cd rename-rename-add-dest &&
946
947                 >a &&
948                 git add a &&
949                 git commit -m A &&
950                 git tag A &&
951
952                 git checkout -b B A &&
953                 git mv a b &&
954                 printf "1\n2\n3\n4\n5\n6\n7\n" >c &&
955                 git add c &&
956                 git commit -m B &&
957
958                 git checkout -b C A &&
959                 git mv a c &&
960                 git commit -m C &&
961
962                 git checkout B^0 &&
963                 git merge --no-commit -s ours C^0 &&
964                 git mv b a &&
965                 git commit -m "D is like B but renames b back to a" &&
966                 git tag D &&
967
968                 git checkout B^0 &&
969                 git merge --no-commit -s ours C^0 &&
970                 git mv b a &&
971                 echo 8 >>c &&
972                 git add c &&
973                 git commit -m "E like D but has mod in c" &&
974                 git tag E
975         )
976 '
977
978 test_expect_success 'virtual merge base handles rename/rename(1to2)/add-dest' '
979         (
980                 cd rename-rename-add-dest &&
981
982                 git checkout D^0 &&
983
984                 git merge -s recursive E^0 &&
985
986                 git ls-files -s >out &&
987                 test_line_count = 2 out &&
988                 git ls-files -u >out &&
989                 test_line_count = 0 out &&
990                 git ls-files -o >out &&
991                 test_line_count = 1 out &&
992
993                 git rev-parse >expect \
994                         A:a   E:c     &&
995                 git rev-parse   >actual \
996                         :0:a  :0:c      &&
997                 test_cmp expect actual
998         )
999 '
1000
1001 #
1002 # criss-cross with modify/modify on a symlink:
1003 #
1004 #      B   D
1005 #      o---o
1006 #     / \ / \
1007 #  A o   X   ? F
1008 #     \ / \ /
1009 #      o---o
1010 #      C   E
1011 #
1012 #   Commit A: simple simlink fickle->lagoon
1013 #   Commit B: redirect fickle->disneyland
1014 #   Commit C: redirect fickle->home
1015 #   Commit D: merge B&C, resolving in favor of B
1016 #   Commit E: merge B&C, resolving in favor of C
1017 #
1018 # This is an obvious modify/modify conflict for the symlink 'fickle'.  Can
1019 # git detect it?
1020
1021 test_expect_success 'setup symlink modify/modify' '
1022         test_create_repo symlink-modify-modify &&
1023         (
1024                 cd symlink-modify-modify &&
1025
1026                 test_ln_s_add lagoon fickle &&
1027                 git commit -m A &&
1028                 git tag A &&
1029
1030                 git checkout -b B A &&
1031                 git rm fickle &&
1032                 test_ln_s_add disneyland fickle &&
1033                 git commit -m B &&
1034
1035                 git checkout -b C A &&
1036                 git rm fickle &&
1037                 test_ln_s_add home fickle &&
1038                 git add fickle &&
1039                 git commit -m C &&
1040
1041                 git checkout -q B^0 &&
1042                 git merge -s ours -m D C^0 &&
1043                 git tag D &&
1044
1045                 git checkout -q C^0 &&
1046                 git merge -s ours -m E B^0 &&
1047                 git tag E
1048         )
1049 '
1050
1051 test_expect_failure 'check symlink modify/modify' '
1052         (
1053                 cd symlink-modify-modify &&
1054
1055                 git checkout D^0 &&
1056
1057                 test_must_fail git merge -s recursive E^0 &&
1058
1059                 git ls-files -s >out &&
1060                 test_line_count = 3 out &&
1061                 git ls-files -u >out &&
1062                 test_line_count = 3 out &&
1063                 git ls-files -o >out &&
1064                 test_line_count = 1 out
1065         )
1066 '
1067
1068 #
1069 # criss-cross with add/add of a symlink:
1070 #
1071 #      B   D
1072 #      o---o
1073 #     / \ / \
1074 #  A o   X   ? F
1075 #     \ / \ /
1076 #      o---o
1077 #      C   E
1078 #
1079 #   Commit A: No symlink or path exists yet
1080 #   Commit B: set up symlink: fickle->disneyland
1081 #   Commit C: set up symlink: fickle->home
1082 #   Commit D: merge B&C, resolving in favor of B
1083 #   Commit E: merge B&C, resolving in favor of C
1084 #
1085 # This is an obvious add/add conflict for the symlink 'fickle'.  Can
1086 # git detect it?
1087
1088 test_expect_success 'setup symlink add/add' '
1089         test_create_repo symlink-add-add &&
1090         (
1091                 cd symlink-add-add &&
1092
1093                 touch ignoreme &&
1094                 git add ignoreme &&
1095                 git commit -m A &&
1096                 git tag A &&
1097
1098                 git checkout -b B A &&
1099                 test_ln_s_add disneyland fickle &&
1100                 git commit -m B &&
1101
1102                 git checkout -b C A &&
1103                 test_ln_s_add home fickle &&
1104                 git add fickle &&
1105                 git commit -m C &&
1106
1107                 git checkout -q B^0 &&
1108                 git merge -s ours -m D C^0 &&
1109                 git tag D &&
1110
1111                 git checkout -q C^0 &&
1112                 git merge -s ours -m E B^0 &&
1113                 git tag E
1114         )
1115 '
1116
1117 test_expect_failure 'check symlink add/add' '
1118         (
1119                 cd symlink-add-add &&
1120
1121                 git checkout D^0 &&
1122
1123                 test_must_fail git merge -s recursive E^0 &&
1124
1125                 git ls-files -s >out &&
1126                 test_line_count = 2 out &&
1127                 git ls-files -u >out &&
1128                 test_line_count = 2 out &&
1129                 git ls-files -o >out &&
1130                 test_line_count = 1 out
1131         )
1132 '
1133
1134 #
1135 # criss-cross with modify/modify on a submodule:
1136 #
1137 #      B   D
1138 #      o---o
1139 #     / \ / \
1140 #  A o   X   ? F
1141 #     \ / \ /
1142 #      o---o
1143 #      C   E
1144 #
1145 #   Commit A: simple submodule repo
1146 #   Commit B: update repo
1147 #   Commit C: update repo differently
1148 #   Commit D: merge B&C, resolving in favor of B
1149 #   Commit E: merge B&C, resolving in favor of C
1150 #
1151 # This is an obvious modify/modify conflict for the submodule 'repo'.  Can
1152 # git detect it?
1153
1154 test_expect_success 'setup submodule modify/modify' '
1155         test_create_repo submodule-modify-modify &&
1156         (
1157                 cd submodule-modify-modify &&
1158
1159                 test_create_repo submod &&
1160                 (
1161                         cd submod &&
1162                         touch file-A &&
1163                         git add file-A &&
1164                         git commit -m A &&
1165                         git tag A &&
1166
1167                         git checkout -b B A &&
1168                         touch file-B &&
1169                         git add file-B &&
1170                         git commit -m B &&
1171                         git tag B &&
1172
1173                         git checkout -b C A &&
1174                         touch file-C &&
1175                         git add file-C &&
1176                         git commit -m C &&
1177                         git tag C
1178                 ) &&
1179
1180                 git -C submod reset --hard A &&
1181                 git add submod &&
1182                 git commit -m A &&
1183                 git tag A &&
1184
1185                 git checkout -b B A &&
1186                 git -C submod reset --hard B &&
1187                 git add submod &&
1188                 git commit -m B &&
1189
1190                 git checkout -b C A &&
1191                 git -C submod reset --hard C &&
1192                 git add submod &&
1193                 git commit -m C &&
1194
1195                 git checkout -q B^0 &&
1196                 git merge -s ours -m D C^0 &&
1197                 git tag D &&
1198
1199                 git checkout -q C^0 &&
1200                 git merge -s ours -m E B^0 &&
1201                 git tag E
1202         )
1203 '
1204
1205 test_expect_failure 'check submodule modify/modify' '
1206         (
1207                 cd submodule-modify-modify &&
1208
1209                 git checkout D^0 &&
1210
1211                 test_must_fail git merge -s recursive E^0 &&
1212
1213                 git ls-files -s >out &&
1214                 test_line_count = 3 out &&
1215                 git ls-files -u >out &&
1216                 test_line_count = 3 out &&
1217                 git ls-files -o >out &&
1218                 test_line_count = 1 out
1219         )
1220 '
1221
1222 #
1223 # criss-cross with add/add on a submodule:
1224 #
1225 #      B   D
1226 #      o---o
1227 #     / \ / \
1228 #  A o   X   ? F
1229 #     \ / \ /
1230 #      o---o
1231 #      C   E
1232 #
1233 #   Commit A: nothing of note
1234 #   Commit B: introduce submodule repo
1235 #   Commit C: introduce submodule repo at different commit
1236 #   Commit D: merge B&C, resolving in favor of B
1237 #   Commit E: merge B&C, resolving in favor of C
1238 #
1239 # This is an obvious add/add conflict for the submodule 'repo'.  Can
1240 # git detect it?
1241
1242 test_expect_success 'setup submodule add/add' '
1243         test_create_repo submodule-add-add &&
1244         (
1245                 cd submodule-add-add &&
1246
1247                 test_create_repo submod &&
1248                 (
1249                         cd submod &&
1250                         touch file-A &&
1251                         git add file-A &&
1252                         git commit -m A &&
1253                         git tag A &&
1254
1255                         git checkout -b B A &&
1256                         touch file-B &&
1257                         git add file-B &&
1258                         git commit -m B &&
1259                         git tag B &&
1260
1261                         git checkout -b C A &&
1262                         touch file-C &&
1263                         git add file-C &&
1264                         git commit -m C &&
1265                         git tag C
1266                 ) &&
1267
1268                 touch irrelevant-file &&
1269                 git add irrelevant-file &&
1270                 git commit -m A &&
1271                 git tag A &&
1272
1273                 git checkout -b B A &&
1274                 git -C submod reset --hard B &&
1275                 git add submod &&
1276                 git commit -m B &&
1277
1278                 git checkout -b C A &&
1279                 git -C submod reset --hard C &&
1280                 git add submod &&
1281                 git commit -m C &&
1282
1283                 git checkout -q B^0 &&
1284                 git merge -s ours -m D C^0 &&
1285                 git tag D &&
1286
1287                 git checkout -q C^0 &&
1288                 git merge -s ours -m E B^0 &&
1289                 git tag E
1290         )
1291 '
1292
1293 test_expect_failure 'check submodule add/add' '
1294         (
1295                 cd submodule-add-add &&
1296
1297                 git checkout D^0 &&
1298
1299                 test_must_fail git merge -s recursive E^0 &&
1300
1301                 git ls-files -s >out &&
1302                 test_line_count = 3 out &&
1303                 git ls-files -u >out &&
1304                 test_line_count = 2 out &&
1305                 git ls-files -o >out &&
1306                 test_line_count = 1 out
1307         )
1308 '
1309
1310 #
1311 # criss-cross with conflicting entry types:
1312 #
1313 #      B   D
1314 #      o---o
1315 #     / \ / \
1316 #  A o   X   ? F
1317 #     \ / \ /
1318 #      o---o
1319 #      C   E
1320 #
1321 #   Commit A: nothing of note
1322 #   Commit B: introduce submodule 'path'
1323 #   Commit C: introduce symlink 'path'
1324 #   Commit D: merge B&C, resolving in favor of B
1325 #   Commit E: merge B&C, resolving in favor of C
1326 #
1327 # This is an obvious add/add conflict for 'path'.  Can git detect it?
1328
1329 test_expect_success 'setup conflicting entry types (submodule vs symlink)' '
1330         test_create_repo submodule-symlink-add-add &&
1331         (
1332                 cd submodule-symlink-add-add &&
1333
1334                 test_create_repo path &&
1335                 (
1336                         cd path &&
1337                         touch file-B &&
1338                         git add file-B &&
1339                         git commit -m B &&
1340                         git tag B
1341                 ) &&
1342
1343                 touch irrelevant-file &&
1344                 git add irrelevant-file &&
1345                 git commit -m A &&
1346                 git tag A &&
1347
1348                 git checkout -b B A &&
1349                 git -C path reset --hard B &&
1350                 git add path &&
1351                 git commit -m B &&
1352
1353                 git checkout -b C A &&
1354                 rm -rf path/ &&
1355                 test_ln_s_add irrelevant-file path &&
1356                 git commit -m C &&
1357
1358                 git checkout -q B^0 &&
1359                 git merge -s ours -m D C^0 &&
1360                 git tag D &&
1361
1362                 git checkout -q C^0 &&
1363                 git merge -s ours -m E B^0 &&
1364                 git tag E
1365         )
1366 '
1367
1368 test_expect_failure 'check conflicting entry types (submodule vs symlink)' '
1369         (
1370                 cd submodule-symlink-add-add &&
1371
1372                 git checkout D^0 &&
1373
1374                 test_must_fail git merge -s recursive E^0 &&
1375
1376                 git ls-files -s >out &&
1377                 test_line_count = 3 out &&
1378                 git ls-files -u >out &&
1379                 test_line_count = 2 out &&
1380                 git ls-files -o >out &&
1381                 test_line_count = 1 out
1382         )
1383 '
1384
1385 #
1386 # criss-cross with regular files that have conflicting modes:
1387 #
1388 #      B   D
1389 #      o---o
1390 #     / \ / \
1391 #  A o   X   ? F
1392 #     \ / \ /
1393 #      o---o
1394 #      C   E
1395 #
1396 #   Commit A: nothing of note
1397 #   Commit B: introduce file source_me.bash, not executable
1398 #   Commit C: introduce file source_me.bash, executable
1399 #   Commit D: merge B&C, resolving in favor of B
1400 #   Commit E: merge B&C, resolving in favor of C
1401 #
1402 # This is an obvious add/add mode conflict.  Can git detect it?
1403
1404 test_expect_success 'setup conflicting modes for regular file' '
1405         test_create_repo regular-file-mode-conflict &&
1406         (
1407                 cd regular-file-mode-conflict &&
1408
1409                 touch irrelevant-file &&
1410                 git add irrelevant-file &&
1411                 git commit -m A &&
1412                 git tag A &&
1413
1414                 git checkout -b B A &&
1415                 echo "command_to_run" >source_me.bash &&
1416                 git add source_me.bash &&
1417                 git commit -m B &&
1418
1419                 git checkout -b C A &&
1420                 echo "command_to_run" >source_me.bash &&
1421                 git add source_me.bash &&
1422                 test_chmod +x source_me.bash &&
1423                 git commit -m C &&
1424
1425                 git checkout -q B^0 &&
1426                 git merge -s ours -m D C^0 &&
1427                 git tag D &&
1428
1429                 git checkout -q C^0 &&
1430                 git merge -s ours -m E B^0 &&
1431                 git tag E
1432         )
1433 '
1434
1435 test_expect_failure 'check conflicting modes for regular file' '
1436         (
1437                 cd regular-file-mode-conflict &&
1438
1439                 git checkout D^0 &&
1440
1441                 test_must_fail git merge -s recursive E^0 &&
1442
1443                 git ls-files -s >out &&
1444                 test_line_count = 3 out &&
1445                 git ls-files -u >out &&
1446                 test_line_count = 2 out &&
1447                 git ls-files -o >out &&
1448                 test_line_count = 1 out
1449         )
1450 '
1451
1452 # Setup:
1453 #          L1---L2
1454 #         /  \ /  \
1455 #   master    X    ?
1456 #         \  / \  /
1457 #          R1---R2
1458 #
1459 # Where:
1460 #   master has two files, named 'b' and 'a'
1461 #   branches L1 and R1 both modify each of the two files in conflicting ways
1462 #
1463 #   L2 is a merge of R1 into L1; more on it later.
1464 #   R2 is a merge of L1 into R1; more on it later.
1465 #
1466 #   X is an auto-generated merge-base used when merging L2 and R2.
1467 #   since X is a merge of L1 and R1, it has conflicting versions of each file
1468 #
1469 #   More about L2 and R2:
1470 #     - both resolve the conflicts in 'b' and 'a' differently
1471 #     - L2 renames 'b' to 'm'
1472 #     - R2 renames 'a' to 'm'
1473 #
1474 #   In the end, in file 'm' we have four different conflicting files (from
1475 #   two versions of 'b' and two of 'a').  In addition, if
1476 #   merge.conflictstyle is diff3, then the base version also has
1477 #   conflict markers of its own, leading to a total of three levels of
1478 #   conflict markers.  This is a pretty weird corner case, but we just want
1479 #   to ensure that we handle it as well as practical.
1480
1481 test_expect_success 'setup nested conflicts' '
1482         test_create_repo nested_conflicts &&
1483         (
1484                 cd nested_conflicts &&
1485
1486                 # Create some related files now
1487                 for i in $(test_seq 1 10)
1488                 do
1489                         echo Random base content line $i
1490                 done >initial &&
1491
1492                 cp initial b_L1 &&
1493                 cp initial b_R1 &&
1494                 cp initial b_L2 &&
1495                 cp initial b_R2 &&
1496                 cp initial a_L1 &&
1497                 cp initial a_R1 &&
1498                 cp initial a_L2 &&
1499                 cp initial a_R2 &&
1500
1501                 test_write_lines b b_L1 >>b_L1 &&
1502                 test_write_lines b b_R1 >>b_R1 &&
1503                 test_write_lines b b_L2 >>b_L2 &&
1504                 test_write_lines b b_R2 >>b_R2 &&
1505                 test_write_lines a a_L1 >>a_L1 &&
1506                 test_write_lines a a_R1 >>a_R1 &&
1507                 test_write_lines a a_L2 >>a_L2 &&
1508                 test_write_lines a a_R2 >>a_R2 &&
1509
1510                 # Setup original commit (or merge-base), consisting of
1511                 # files named "b" and "a"
1512                 cp initial b &&
1513                 cp initial a &&
1514                 echo b >>b &&
1515                 echo a >>a &&
1516                 git add b a &&
1517                 test_tick && git commit -m initial &&
1518
1519                 git branch L &&
1520                 git branch R &&
1521
1522                 # Handle the left side
1523                 git checkout L &&
1524                 mv -f b_L1 b &&
1525                 mv -f a_L1 a &&
1526                 git add b a &&
1527                 test_tick && git commit -m "version L1 of files" &&
1528                 git tag L1 &&
1529
1530                 # Handle the right side
1531                 git checkout R &&
1532                 mv -f b_R1 b &&
1533                 mv -f a_R1 a &&
1534                 git add b a &&
1535                 test_tick && git commit -m "version R1 of files" &&
1536                 git tag R1 &&
1537
1538                 # Create first merge on left side
1539                 git checkout L &&
1540                 test_must_fail git merge R1 &&
1541                 mv -f b_L2 b &&
1542                 mv -f a_L2 a &&
1543                 git add b a &&
1544                 git mv b m &&
1545                 test_tick && git commit -m "left merge, rename b->m" &&
1546                 git tag L2 &&
1547
1548                 # Create first merge on right side
1549                 git checkout R &&
1550                 test_must_fail git merge L1 &&
1551                 mv -f b_R2 b &&
1552                 mv -f a_R2 a &&
1553                 git add b a &&
1554                 git mv a m &&
1555                 test_tick && git commit -m "right merge, rename a->m" &&
1556                 git tag R2
1557         )
1558 '
1559
1560 test_expect_success 'check nested conflicts' '
1561         (
1562                 cd nested_conflicts &&
1563
1564                 git clean -f &&
1565                 MASTER=$(git rev-parse --short master) &&
1566                 git checkout L2^0 &&
1567
1568                 # Merge must fail; there is a conflict
1569                 test_must_fail git -c merge.conflictstyle=diff3 merge -s recursive R2^0 &&
1570
1571                 # Make sure the index has the right number of entries
1572                 git ls-files -s >out &&
1573                 test_line_count = 2 out &&
1574                 git ls-files -u >out &&
1575                 test_line_count = 2 out &&
1576                 # Ensure we have the correct number of untracked files
1577                 git ls-files -o >out &&
1578                 test_line_count = 1 out &&
1579
1580                 # Create a and b from virtual merge base X
1581                 git cat-file -p master:a >base &&
1582                 git cat-file -p L1:a >ours &&
1583                 git cat-file -p R1:a >theirs &&
1584                 test_must_fail git merge-file --diff3 \
1585                         -L "Temporary merge branch 1" \
1586                         -L "$MASTER"  \
1587                         -L "Temporary merge branch 2" \
1588                         ours  \
1589                         base  \
1590                         theirs &&
1591                 sed -e "s/^\([<|=>]\)/\1\1/" ours >vmb_a &&
1592
1593                 git cat-file -p master:b >base &&
1594                 git cat-file -p L1:b >ours &&
1595                 git cat-file -p R1:b >theirs &&
1596                 test_must_fail git merge-file --diff3 \
1597                         -L "Temporary merge branch 1" \
1598                         -L "$MASTER"  \
1599                         -L "Temporary merge branch 2" \
1600                         ours  \
1601                         base  \
1602                         theirs &&
1603                 sed -e "s/^\([<|=>]\)/\1\1/" ours >vmb_b &&
1604
1605                 # Compare :2:m to expected values
1606                 git cat-file -p L2:m >ours &&
1607                 git cat-file -p R2:b >theirs &&
1608                 test_must_fail git merge-file --diff3  \
1609                         -L "HEAD:m"                    \
1610                         -L "merged common ancestors:b" \
1611                         -L "R2^0:b"                    \
1612                         ours                           \
1613                         vmb_b                          \
1614                         theirs                         &&
1615                 sed -e "s/^\([<|=>]\)/\1\1/" ours >m_stage_2 &&
1616                 git cat-file -p :2:m >actual &&
1617                 test_cmp m_stage_2 actual &&
1618
1619                 # Compare :3:m to expected values
1620                 git cat-file -p L2:a >ours &&
1621                 git cat-file -p R2:m >theirs &&
1622                 test_must_fail git merge-file --diff3  \
1623                         -L "HEAD:a"                    \
1624                         -L "merged common ancestors:a" \
1625                         -L "R2^0:m"                    \
1626                         ours                           \
1627                         vmb_a                          \
1628                         theirs                         &&
1629                 sed -e "s/^\([<|=>]\)/\1\1/" ours >m_stage_3 &&
1630                 git cat-file -p :3:m >actual &&
1631                 test_cmp m_stage_3 actual &&
1632
1633                 # Compare m to expected contents
1634                 >empty &&
1635                 cp m_stage_2 expected_final_m &&
1636                 test_must_fail git merge-file --diff3 \
1637                         -L "HEAD"                     \
1638                         -L "merged common ancestors"  \
1639                         -L "R2^0"                     \
1640                         expected_final_m              \
1641                         empty                         \
1642                         m_stage_3                     &&
1643                 test_cmp expected_final_m m
1644         )
1645 '
1646
1647 # Setup:
1648 #          L1---L2---L3
1649 #         /  \ /  \ /  \
1650 #   master    X1   X2   ?
1651 #         \  / \  / \  /
1652 #          R1---R2---R3
1653 #
1654 # Where:
1655 #   master has one file named 'content'
1656 #   branches L1 and R1 both modify each of the two files in conflicting ways
1657 #
1658 #   L<n> (n>1) is a merge of R<n-1> into L<n-1>
1659 #   R<n> (n>1) is a merge of L<n-1> into R<n-1>
1660 #   L<n> and R<n> resolve the conflicts differently.
1661 #
1662 #   X<n> is an auto-generated merge-base used when merging L<n+1> and R<n+1>.
1663 #   By construction, X1 has conflict markers due to conflicting versions.
1664 #   X2, due to using merge.conflictstyle=3, has nested conflict markers.
1665 #
1666 #   So, merging R3 into L3 using merge.conflictstyle=3 should show the
1667 #   nested conflict markers from X2 in the base version -- that means we
1668 #   have three levels of conflict markers.  Can we distinguish all three?
1669
1670 test_expect_success 'setup virtual merge base with nested conflicts' '
1671         test_create_repo virtual_merge_base_has_nested_conflicts &&
1672         (
1673                 cd virtual_merge_base_has_nested_conflicts &&
1674
1675                 # Create some related files now
1676                 for i in $(test_seq 1 10)
1677                 do
1678                         echo Random base content line $i
1679                 done >content &&
1680
1681                 # Setup original commit
1682                 git add content &&
1683                 test_tick && git commit -m initial &&
1684
1685                 git branch L &&
1686                 git branch R &&
1687
1688                 # Create L1
1689                 git checkout L &&
1690                 echo left >>content &&
1691                 git add content &&
1692                 test_tick && git commit -m "version L1 of content" &&
1693                 git tag L1 &&
1694
1695                 # Create R1
1696                 git checkout R &&
1697                 echo right >>content &&
1698                 git add content &&
1699                 test_tick && git commit -m "version R1 of content" &&
1700                 git tag R1 &&
1701
1702                 # Create L2
1703                 git checkout L &&
1704                 test_must_fail git -c merge.conflictstyle=diff3 merge R1 &&
1705                 git checkout L1 content &&
1706                 test_tick && git commit -m "version L2 of content" &&
1707                 git tag L2 &&
1708
1709                 # Create R2
1710                 git checkout R &&
1711                 test_must_fail git -c merge.conflictstyle=diff3 merge L1 &&
1712                 git checkout R1 content &&
1713                 test_tick && git commit -m "version R2 of content" &&
1714                 git tag R2 &&
1715
1716                 # Create L3
1717                 git checkout L &&
1718                 test_must_fail git -c merge.conflictstyle=diff3 merge R2 &&
1719                 git checkout L1 content &&
1720                 test_tick && git commit -m "version L3 of content" &&
1721                 git tag L3 &&
1722
1723                 # Create R3
1724                 git checkout R &&
1725                 test_must_fail git -c merge.conflictstyle=diff3 merge L2 &&
1726                 git checkout R1 content &&
1727                 test_tick && git commit -m "version R3 of content" &&
1728                 git tag R3
1729         )
1730 '
1731
1732 test_expect_success 'check virtual merge base with nested conflicts' '
1733         (
1734                 cd virtual_merge_base_has_nested_conflicts &&
1735
1736                 MASTER=$(git rev-parse --short master) &&
1737                 git checkout L3^0 &&
1738
1739                 # Merge must fail; there is a conflict
1740                 test_must_fail git -c merge.conflictstyle=diff3 merge -s recursive R3^0 &&
1741
1742                 # Make sure the index has the right number of entries
1743                 git ls-files -s >out &&
1744                 test_line_count = 3 out &&
1745                 git ls-files -u >out &&
1746                 test_line_count = 3 out &&
1747                 # Ensure we have the correct number of untracked files
1748                 git ls-files -o >out &&
1749                 test_line_count = 1 out &&
1750
1751                 # Compare :[23]:content to expected values
1752                 git rev-parse L1:content R1:content >expect &&
1753                 git rev-parse :2:content :3:content >actual &&
1754                 test_cmp expect actual &&
1755
1756                 # Imitate X1 merge base, except without long enough conflict
1757                 # markers because a subsequent sed will modify them.  Put
1758                 # result into vmb.
1759                 git cat-file -p master:content >base &&
1760                 git cat-file -p L:content >left &&
1761                 git cat-file -p R:content >right &&
1762                 cp left merged-once &&
1763                 test_must_fail git merge-file --diff3 \
1764                         -L "Temporary merge branch 1" \
1765                         -L "$MASTER"  \
1766                         -L "Temporary merge branch 2" \
1767                         merged-once \
1768                         base        \
1769                         right       &&
1770                 sed -e "s/^\([<|=>]\)/\1\1\1/" merged-once >vmb &&
1771
1772                 # Imitate X2 merge base, overwriting vmb.  Note that we
1773                 # extend both sets of conflict markers to make them longer
1774                 # with the sed command.
1775                 cp left merged-twice &&
1776                 test_must_fail git merge-file --diff3 \
1777                         -L "Temporary merge branch 1" \
1778                         -L "merged common ancestors"  \
1779                         -L "Temporary merge branch 2" \
1780                         merged-twice \
1781                         vmb          \
1782                         right        &&
1783                 sed -e "s/^\([<|=>]\)/\1\1\1/" merged-twice >vmb &&
1784
1785                 # Compare :1:content to expected value
1786                 git cat-file -p :1:content >actual &&
1787                 test_cmp vmb actual &&
1788
1789                 # Determine expected content in final outer merge, compare to
1790                 # what the merge generated.
1791                 cp -f left expect &&
1792                 test_must_fail git merge-file --diff3                      \
1793                         -L "HEAD"  -L "merged common ancestors"  -L "R3^0" \
1794                         expect     vmb                           right     &&
1795                 test_cmp expect content
1796         )
1797 '
1798
1799 test_done