Add new `git update` tool
[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 get_clean_checkout () {
8         git reset --hard &&
9         git clean -fdqx &&
10         git checkout "$1"
11 }
12
13 #
14 #  L1  L2
15 #   o---o
16 #  / \ / \
17 # o   X   ?
18 #  \ / \ /
19 #   o---o
20 #  R1  R2
21 #
22
23 test_expect_success 'setup basic criss-cross + rename with no modifications' '
24         ten="0 1 2 3 4 5 6 7 8 9" &&
25         for i in $ten
26         do
27                 echo line $i in a sample file
28         done >one &&
29         for i in $ten
30         do
31                 echo line $i in another sample file
32         done >two &&
33         git add one two &&
34         test_tick && git commit -m initial &&
35
36         git branch L1 &&
37         git checkout -b R1 &&
38         git mv one three &&
39         test_tick && git commit -m R1 &&
40
41         git checkout L1 &&
42         git mv two three &&
43         test_tick && git commit -m L1 &&
44
45         git checkout L1^0 &&
46         test_tick && git merge -s ours R1 &&
47         git tag L2 &&
48
49         git checkout R1^0 &&
50         test_tick && git merge -s ours L1 &&
51         git tag R2
52 '
53
54 test_expect_success 'merge simple rename+criss-cross with no modifications' '
55         git reset --hard &&
56         git checkout L2^0 &&
57
58         test_must_fail git merge -s recursive R2^0 &&
59
60         test 2 = $(git ls-files -s | wc -l) &&
61         test 2 = $(git ls-files -u | wc -l) &&
62         test 2 = $(git ls-files -o | wc -l) &&
63
64         test $(git rev-parse :2:three) = $(git rev-parse L2:three) &&
65         test $(git rev-parse :3:three) = $(git rev-parse R2:three) &&
66
67         test $(git rev-parse L2:three) = $(git hash-object three~HEAD) &&
68         test $(git rev-parse R2:three) = $(git hash-object three~R2^0)
69 '
70
71 #
72 # Same as before, but modify L1 slightly:
73 #
74 #  L1m L2
75 #   o---o
76 #  / \ / \
77 # o   X   ?
78 #  \ / \ /
79 #   o---o
80 #  R1  R2
81 #
82
83 test_expect_success 'setup criss-cross + rename merges with basic modification' '
84         git rm -rf . &&
85         git clean -fdqx &&
86         rm -rf .git &&
87         git init &&
88
89         ten="0 1 2 3 4 5 6 7 8 9" &&
90         for i in $ten
91         do
92                 echo line $i in a sample file
93         done >one &&
94         for i in $ten
95         do
96                 echo line $i in another sample file
97         done >two &&
98         git add one two &&
99         test_tick && git commit -m initial &&
100
101         git branch L1 &&
102         git checkout -b R1 &&
103         git mv one three &&
104         echo more >>two &&
105         git add two &&
106         test_tick && git commit -m R1 &&
107
108         git checkout L1 &&
109         git mv two three &&
110         test_tick && git commit -m L1 &&
111
112         git checkout L1^0 &&
113         test_tick && git merge -s ours R1 &&
114         git tag L2 &&
115
116         git checkout R1^0 &&
117         test_tick && git merge -s ours L1 &&
118         git tag R2
119 '
120
121 test_expect_success 'merge criss-cross + rename merges with basic modification' '
122         git reset --hard &&
123         git checkout L2^0 &&
124
125         test_must_fail git merge -s recursive R2^0 &&
126
127         test 2 = $(git ls-files -s | wc -l) &&
128         test 2 = $(git ls-files -u | wc -l) &&
129         test 2 = $(git ls-files -o | wc -l) &&
130
131         test $(git rev-parse :2:three) = $(git rev-parse L2:three) &&
132         test $(git rev-parse :3:three) = $(git rev-parse R2:three) &&
133
134         test $(git rev-parse L2:three) = $(git hash-object three~HEAD) &&
135         test $(git rev-parse R2:three) = $(git hash-object three~R2^0)
136 '
137
138 #
139 # For the next test, we start with three commits in two lines of development
140 # which setup a rename/add conflict:
141 #   Commit A: File 'a' exists
142 #   Commit B: Rename 'a' -> 'new_a'
143 #   Commit C: Modify 'a', create different 'new_a'
144 # Later, two different people merge and resolve differently:
145 #   Commit D: Merge B & C, ignoring separately created 'new_a'
146 #   Commit E: Merge B & C making use of some piece of secondary 'new_a'
147 # Finally, someone goes to merge D & E.  Does git detect the conflict?
148 #
149 #      B   D
150 #      o---o
151 #     / \ / \
152 #  A o   X   ? F
153 #     \ / \ /
154 #      o---o
155 #      C   E
156 #
157
158 test_expect_success 'setup differently handled merges of rename/add conflict' '
159         git rm -rf . &&
160         git clean -fdqx &&
161         rm -rf .git &&
162         git init &&
163
164         printf "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n" >a &&
165         git add a &&
166         test_tick && git commit -m A &&
167
168         git branch B &&
169         git checkout -b C &&
170         echo 10 >>a &&
171         echo "other content" >>new_a &&
172         git add a new_a &&
173         test_tick && git commit -m C &&
174
175         git checkout B &&
176         git mv a new_a &&
177         test_tick && git commit -m B &&
178
179         git checkout B^0 &&
180         test_must_fail git merge C &&
181         git clean -f &&
182         test_tick && git commit -m D &&
183         git tag D &&
184
185         git checkout C^0 &&
186         test_must_fail git merge B &&
187         rm new_a~HEAD new_a &&
188         printf "Incorrectly merged content" >>new_a &&
189         git add -u &&
190         test_tick && git commit -m E &&
191         git tag E
192 '
193
194 test_expect_success 'git detects differently handled merges conflict' '
195         git reset --hard &&
196         git checkout D^0 &&
197
198         test_must_fail git merge -s recursive E^0 &&
199
200         test 3 = $(git ls-files -s | wc -l) &&
201         test 3 = $(git ls-files -u | wc -l) &&
202         test 0 = $(git ls-files -o | wc -l) &&
203
204         test $(git rev-parse :2:new_a) = $(git rev-parse D:new_a) &&
205         test $(git rev-parse :3:new_a) = $(git rev-parse E:new_a) &&
206
207         git cat-file -p B:new_a >>merged &&
208         git cat-file -p C:new_a >>merge-me &&
209         >empty &&
210         test_must_fail git merge-file \
211                 -L "Temporary merge branch 2" \
212                 -L "" \
213                 -L "Temporary merge branch 1" \
214                 merged empty merge-me &&
215         test $(git rev-parse :1:new_a) = $(git hash-object merged)
216 '
217
218 #
219 # criss-cross + modify/delete:
220 #
221 #      B   D
222 #      o---o
223 #     / \ / \
224 #  A o   X   ? F
225 #     \ / \ /
226 #      o---o
227 #      C   E
228 #
229 #   Commit A: file with contents 'A\n'
230 #   Commit B: file with contents 'B\n'
231 #   Commit C: file not present
232 #   Commit D: file with contents 'B\n'
233 #   Commit E: file not present
234 #
235 # Merging commits D & E should result in modify/delete conflict.
236
237 test_expect_success 'setup criss-cross + modify/delete resolved differently' '
238         git rm -rf . &&
239         git clean -fdqx &&
240         rm -rf .git &&
241         git init &&
242
243         echo A >file &&
244         git add file &&
245         test_tick &&
246         git commit -m A &&
247
248         git branch B &&
249         git checkout -b C &&
250         git rm file &&
251         test_tick &&
252         git commit -m C &&
253
254         git checkout B &&
255         echo B >file &&
256         git add file &&
257         test_tick &&
258         git commit -m B &&
259
260         git checkout B^0 &&
261         test_must_fail git merge C &&
262         echo B >file &&
263         git add file &&
264         test_tick &&
265         git commit -m D &&
266         git tag D &&
267
268         git checkout C^0 &&
269         test_must_fail git merge B &&
270         git rm file &&
271         test_tick &&
272         git commit -m E &&
273         git tag E
274 '
275
276 test_expect_success 'git detects conflict merging criss-cross+modify/delete' '
277         git checkout D^0 &&
278
279         test_must_fail git merge -s recursive E^0 &&
280
281         test 2 -eq $(git ls-files -s | wc -l) &&
282         test 2 -eq $(git ls-files -u | wc -l) &&
283
284         test $(git rev-parse :1:file) = $(git rev-parse master:file) &&
285         test $(git rev-parse :2:file) = $(git rev-parse B:file)
286 '
287
288 test_expect_success 'git detects conflict merging criss-cross+modify/delete, reverse direction' '
289         git reset --hard &&
290         git checkout E^0 &&
291
292         test_must_fail git merge -s recursive D^0 &&
293
294         test 2 -eq $(git ls-files -s | wc -l) &&
295         test 2 -eq $(git ls-files -u | wc -l) &&
296
297         test $(git rev-parse :1:file) = $(git rev-parse master:file) &&
298         test $(git rev-parse :3:file) = $(git rev-parse B:file)
299 '
300
301 #
302 # criss-cross + modify/modify with very contrived file contents:
303 #
304 #      B   D
305 #      o---o
306 #     / \ / \
307 #  A o   X   ? F
308 #     \ / \ /
309 #      o---o
310 #      C   E
311 #
312 #   Commit A: file with contents 'A\n'
313 #   Commit B: file with contents 'B\n'
314 #   Commit C: file with contents 'C\n'
315 #   Commit D: file with contents 'D\n'
316 #   Commit E: file with contents:
317 #      <<<<<<< Temporary merge branch 1
318 #      C
319 #      =======
320 #      B
321 #      >>>>>>> Temporary merge branch 2
322 #
323 # Now, when we merge commits D & E, does git detect the conflict?
324
325 test_expect_success 'setup differently handled merges of content conflict' '
326         git clean -fdqx &&
327         rm -rf .git &&
328         git init &&
329
330         echo A >file &&
331         git add file &&
332         test_tick &&
333         git commit -m A &&
334
335         git branch B &&
336         git checkout -b C &&
337         echo C >file &&
338         git add file &&
339         test_tick &&
340         git commit -m C &&
341
342         git checkout B &&
343         echo B >file &&
344         git add file &&
345         test_tick &&
346         git commit -m B &&
347
348         git checkout B^0 &&
349         test_must_fail git merge C &&
350         echo D >file &&
351         git add file &&
352         test_tick &&
353         git commit -m D &&
354         git tag D &&
355
356         git checkout C^0 &&
357         test_must_fail git merge B &&
358         cat <<EOF >file &&
359 <<<<<<< Temporary merge branch 1
360 C
361 =======
362 B
363 >>>>>>> Temporary merge branch 2
364 EOF
365         git add file &&
366         test_tick &&
367         git commit -m E &&
368         git tag E
369 '
370
371 test_expect_failure 'git detects conflict w/ criss-cross+contrived resolution' '
372         git checkout D^0 &&
373
374         test_must_fail git merge -s recursive E^0 &&
375
376         test 3 -eq $(git ls-files -s | wc -l) &&
377         test 3 -eq $(git ls-files -u | wc -l) &&
378         test 0 -eq $(git ls-files -o | wc -l) &&
379
380         test $(git rev-parse :2:file) = $(git rev-parse D:file) &&
381         test $(git rev-parse :3:file) = $(git rev-parse E:file)
382 '
383
384 #
385 # criss-cross + d/f conflict via add/add:
386 #   Commit A: Neither file 'a' nor directory 'a/' exists.
387 #   Commit B: Introduce 'a'
388 #   Commit C: Introduce 'a/file'
389 #   Commit D: Merge B & C, keeping 'a' and deleting 'a/'
390 #
391 # Two different later cases:
392 #   Commit E1: Merge B & C, deleting 'a' but keeping 'a/file'
393 #   Commit E2: Merge B & C, deleting 'a' but keeping a slightly modified 'a/file'
394 #
395 #      B   D
396 #      o---o
397 #     / \ / \
398 #  A o   X   ? F
399 #     \ / \ /
400 #      o---o
401 #      C   E1 or E2
402 #
403 # Merging D & E1 requires we first create a virtual merge base X from
404 # merging A & B in memory.  Now, if X could keep both 'a' and 'a/file' in
405 # the index, then the merge of D & E1 could be resolved cleanly with both
406 # 'a' and 'a/file' removed.  Since git does not currently allow creating
407 # such a tree, the best we can do is have X contain both 'a~<unique>' and
408 # 'a/file' resulting in the merge of D and E1 having a rename/delete
409 # conflict for 'a'.  (Although this merge appears to be unsolvable with git
410 # currently, git could do a lot better than it currently does with these
411 # d/f conflicts, which is the purpose of this test.)
412 #
413 # Merge of D & E2 has similar issues for path 'a', but should always result
414 # in a modify/delete conflict for path 'a/file'.
415 #
416 # We run each merge in both directions, to check for directional issues
417 # with D/F conflict handling.
418 #
419
420 test_expect_success 'setup differently handled merges of directory/file conflict' '
421         git rm -rf . &&
422         git clean -fdqx &&
423         rm -rf .git &&
424         git init &&
425
426         >ignore-me &&
427         git add ignore-me &&
428         test_tick &&
429         git commit -m A &&
430         git tag A &&
431
432         git branch B &&
433         git checkout -b C &&
434         mkdir a &&
435         echo 10 >a/file &&
436         git add a/file &&
437         test_tick &&
438         git commit -m C &&
439
440         git checkout B &&
441         echo 5 >a &&
442         git add a &&
443         test_tick &&
444         git commit -m B &&
445
446         git checkout B^0 &&
447         test_must_fail git merge C &&
448         git clean -f &&
449         rm -rf a/ &&
450         echo 5 >a &&
451         git add a &&
452         test_tick &&
453         git commit -m D &&
454         git tag D &&
455
456         git checkout C^0 &&
457         test_must_fail git merge B &&
458         git clean -f &&
459         git rm --cached a &&
460         echo 10 >a/file &&
461         git add a/file &&
462         test_tick &&
463         git commit -m E1 &&
464         git tag E1 &&
465
466         git checkout C^0 &&
467         test_must_fail git merge B &&
468         git clean -f &&
469         git rm --cached a &&
470         printf "10\n11\n" >a/file &&
471         git add a/file &&
472         test_tick &&
473         git commit -m E2 &&
474         git tag E2
475 '
476
477 test_expect_success 'merge of D & E1 fails but has appropriate contents' '
478         get_clean_checkout D^0 &&
479
480         test_must_fail git merge -s recursive E1^0 &&
481
482         test 2 -eq $(git ls-files -s | wc -l) &&
483         test 1 -eq $(git ls-files -u | wc -l) &&
484         test 0 -eq $(git ls-files -o | wc -l) &&
485
486         test $(git rev-parse :0:ignore-me) = $(git rev-parse A:ignore-me) &&
487         test $(git rev-parse :2:a) = $(git rev-parse B:a)
488 '
489
490 test_expect_success 'merge of E1 & D fails but has appropriate contents' '
491         get_clean_checkout E1^0 &&
492
493         test_must_fail git merge -s recursive D^0 &&
494
495         test 2 -eq $(git ls-files -s | wc -l) &&
496         test 1 -eq $(git ls-files -u | wc -l) &&
497         test 0 -eq $(git ls-files -o | wc -l) &&
498
499         test $(git rev-parse :0:ignore-me) = $(git rev-parse A:ignore-me) &&
500         test $(git rev-parse :3:a) = $(git rev-parse B:a)
501 '
502
503 test_expect_success 'merge of D & E2 fails but has appropriate contents' '
504         get_clean_checkout D^0 &&
505
506         test_must_fail git merge -s recursive E2^0 &&
507
508         test 4 -eq $(git ls-files -s | wc -l) &&
509         test 3 -eq $(git ls-files -u | wc -l) &&
510         test 1 -eq $(git ls-files -o | wc -l) &&
511
512         test $(git rev-parse :2:a) = $(git rev-parse B:a) &&
513         test $(git rev-parse :3:a/file) = $(git rev-parse E2:a/file) &&
514         test $(git rev-parse :1:a/file) = $(git rev-parse C:a/file) &&
515         test $(git rev-parse :0:ignore-me) = $(git rev-parse A:ignore-me) &&
516
517         test -f a~HEAD
518 '
519
520 test_expect_success 'merge of E2 & D fails but has appropriate contents' '
521         get_clean_checkout E2^0 &&
522
523         test_must_fail git merge -s recursive D^0 &&
524
525         test 4 -eq $(git ls-files -s | wc -l) &&
526         test 3 -eq $(git ls-files -u | wc -l) &&
527         test 1 -eq $(git ls-files -o | wc -l) &&
528
529         test $(git rev-parse :3:a) = $(git rev-parse B:a) &&
530         test $(git rev-parse :2:a/file) = $(git rev-parse E2:a/file) &&
531         test $(git rev-parse :1:a/file) = $(git rev-parse C:a/file) &&
532         test $(git rev-parse :0:ignore-me) = $(git rev-parse A:ignore-me) &&
533
534         test -f a~D^0
535 '
536
537 #
538 # criss-cross with rename/rename(1to2)/modify followed by
539 # rename/rename(2to1)/modify:
540 #
541 #      B   D
542 #      o---o
543 #     / \ / \
544 #  A o   X   ? F
545 #     \ / \ /
546 #      o---o
547 #      C   E
548 #
549 #   Commit A: new file: a
550 #   Commit B: rename a->b, modifying by adding a line
551 #   Commit C: rename a->c
552 #   Commit D: merge B&C, resolving conflict by keeping contents in newname
553 #   Commit E: merge B&C, resolving conflict similar to D but adding another line
554 #
555 # There is a conflict merging B & C, but one of filename not of file
556 # content.  Whoever created D and E chose specific resolutions for that
557 # conflict resolution.  Now, since: (1) there is no content conflict
558 # merging B & C, (2) D does not modify that merged content further, and (3)
559 # both D & E resolve the name conflict in the same way, the modification to
560 # newname in E should not cause any conflicts when it is merged with D.
561 # (Note that this can be accomplished by having the virtual merge base have
562 # the merged contents of b and c stored in a file named a, which seems like
563 # the most logical choice anyway.)
564 #
565 # Comment from Junio: I do not necessarily agree with the choice "a", but
566 # it feels sound to say "B and C do not agree what the final pathname
567 # should be, but we know this content was derived from the common A:a so we
568 # use one path whose name is arbitrary in the virtual merge base X between
569 # D and E" and then further let the rename detection to notice that that
570 # arbitrary path gets renamed between X-D to "newname" and X-E also to
571 # "newname" to resolve it as both sides renaming it to the same new
572 # name. It is akin to what we do at the content level, i.e. "B and C do not
573 # agree what the final contents should be, so we leave the conflict marker
574 # but that may cancel out at the final merge stage".
575
576 test_expect_success 'setup rename/rename(1to2)/modify followed by what looks like rename/rename(2to1)/modify' '
577         git reset --hard &&
578         git rm -rf . &&
579         git clean -fdqx &&
580         rm -rf .git &&
581         git init &&
582
583         printf "1\n2\n3\n4\n5\n6\n" >a &&
584         git add a &&
585         git commit -m A &&
586         git tag A &&
587
588         git checkout -b B A &&
589         git mv a b &&
590         echo 7 >>b &&
591         git add -u &&
592         git commit -m B &&
593
594         git checkout -b C A &&
595         git mv a c &&
596         git commit -m C &&
597
598         git checkout -q B^0 &&
599         git merge --no-commit -s ours C^0 &&
600         git mv b newname &&
601         git commit -m "Merge commit C^0 into HEAD" &&
602         git tag D &&
603
604         git checkout -q C^0 &&
605         git merge --no-commit -s ours B^0 &&
606         git mv c newname &&
607         printf "7\n8\n" >>newname &&
608         git add -u &&
609         git commit -m "Merge commit B^0 into HEAD" &&
610         git tag E
611 '
612
613 test_expect_success 'handle rename/rename(1to2)/modify followed by what looks like rename/rename(2to1)/modify' '
614         git checkout D^0 &&
615
616         git merge -s recursive E^0 &&
617
618         test 1 -eq $(git ls-files -s | wc -l) &&
619         test 0 -eq $(git ls-files -u | wc -l) &&
620         test 0 -eq $(git ls-files -o | wc -l) &&
621
622         test $(git rev-parse HEAD:newname) = $(git rev-parse E:newname)
623 '
624
625 #
626 # criss-cross with rename/rename(1to2)/add-source + resolvable modify/modify:
627 #
628 #      B   D
629 #      o---o
630 #     / \ / \
631 #  A o   X   ? F
632 #     \ / \ /
633 #      o---o
634 #      C   E
635 #
636 #   Commit A: new file: a
637 #   Commit B: rename a->b
638 #   Commit C: rename a->c, add different a
639 #   Commit D: merge B&C, keeping b&c and (new) a modified at beginning
640 #   Commit E: merge B&C, keeping b&c and (new) a modified at end
641 #
642 # Merging commits D & E should result in no conflict; doing so correctly
643 # requires getting the virtual merge base (from merging B&C) right, handling
644 # renaming carefully (both in the virtual merge base and later), and getting
645 # content merge handled.
646
647 test_expect_success 'setup criss-cross + rename/rename/add + modify/modify' '
648         git rm -rf . &&
649         git clean -fdqx &&
650         rm -rf .git &&
651         git init &&
652
653         printf "lots\nof\nwords\nand\ncontent\n" >a &&
654         git add a &&
655         git commit -m A &&
656         git tag A &&
657
658         git checkout -b B A &&
659         git mv a b &&
660         git commit -m B &&
661
662         git checkout -b C A &&
663         git mv a c &&
664         printf "2\n3\n4\n5\n6\n7\n" >a &&
665         git add a &&
666         git commit -m C &&
667
668         git checkout B^0 &&
669         git merge --no-commit -s ours C^0 &&
670         git checkout C -- a c &&
671         mv a old_a &&
672         echo 1 >a &&
673         cat old_a >>a &&
674         rm old_a &&
675         git add -u &&
676         git commit -m "Merge commit C^0 into HEAD" &&
677         git tag D &&
678
679         git checkout C^0 &&
680         git merge --no-commit -s ours B^0 &&
681         git checkout B -- b &&
682         echo 8 >>a &&
683         git add -u &&
684         git commit -m "Merge commit B^0 into HEAD" &&
685         git tag E
686 '
687
688 test_expect_failure 'detect rename/rename/add-source for virtual merge-base' '
689         git checkout D^0 &&
690
691         git merge -s recursive E^0 &&
692
693         test 3 -eq $(git ls-files -s | wc -l) &&
694         test 0 -eq $(git ls-files -u | wc -l) &&
695         test 0 -eq $(git ls-files -o | wc -l) &&
696
697         test $(git rev-parse HEAD:b) = $(git rev-parse A:a) &&
698         test $(git rev-parse HEAD:c) = $(git rev-parse A:a) &&
699         test "$(cat a)" = "$(printf "1\n2\n3\n4\n5\n6\n7\n8\n")"
700 '
701
702 #
703 # criss-cross with rename/rename(1to2)/add-dest + simple modify:
704 #
705 #      B   D
706 #      o---o
707 #     / \ / \
708 #  A o   X   ? F
709 #     \ / \ /
710 #      o---o
711 #      C   E
712 #
713 #   Commit A: new file: a
714 #   Commit B: rename a->b, add c
715 #   Commit C: rename a->c
716 #   Commit D: merge B&C, keeping A:a and B:c
717 #   Commit E: merge B&C, keeping A:a and slightly modified c from B
718 #
719 # Merging commits D & E should result in no conflict.  The virtual merge
720 # base of B & C needs to not delete B:c for that to work, though...
721
722 test_expect_success 'setup criss-cross+rename/rename/add-dest + simple modify' '
723         git rm -rf . &&
724         git clean -fdqx &&
725         rm -rf .git &&
726         git init &&
727
728         >a &&
729         git add a &&
730         git commit -m A &&
731         git tag A &&
732
733         git checkout -b B A &&
734         git mv a b &&
735         printf "1\n2\n3\n4\n5\n6\n7\n" >c &&
736         git add c &&
737         git commit -m B &&
738
739         git checkout -b C A &&
740         git mv a c &&
741         git commit -m C &&
742
743         git checkout B^0 &&
744         git merge --no-commit -s ours C^0 &&
745         git mv b a &&
746         git commit -m "D is like B but renames b back to a" &&
747         git tag D &&
748
749         git checkout B^0 &&
750         git merge --no-commit -s ours C^0 &&
751         git mv b a &&
752         echo 8 >>c &&
753         git add c &&
754         git commit -m "E like D but has mod in c" &&
755         git tag E
756 '
757
758 test_expect_success 'virtual merge base handles rename/rename(1to2)/add-dest' '
759         git checkout D^0 &&
760
761         git merge -s recursive E^0 &&
762
763         test 2 -eq $(git ls-files -s | wc -l) &&
764         test 0 -eq $(git ls-files -u | wc -l) &&
765         test 0 -eq $(git ls-files -o | wc -l) &&
766
767         test $(git rev-parse HEAD:a) = $(git rev-parse A:a) &&
768         test $(git rev-parse HEAD:c) = $(git rev-parse E:c)
769 '
770
771 test_done