]> git.ipfire.org Git - thirdparty/git.git/blobdiff - t/t6043-merge-rename-directories.sh
upload-pack: move allow_unadvertised_object_request to upload_pack_data
[thirdparty/git.git] / t / t6043-merge-rename-directories.sh
index 4a71f17edd69a2cb6962cf759aa6ad1b7604c2db..83792c5ef1f5ebbdd49bb1455b262ef9d01145f9 100755 (executable)
@@ -38,7 +38,7 @@ test_description="recursive merge with directory renames"
 #   Commit B: z/{b,c,d,e/f}
 #   Expected: y/{b,c,d,e/f}
 
-test_expect_success '1a-setup: Simple directory rename detection' '
+test_setup_1a () {
        test_create_repo 1a &&
        (
                cd 1a &&
@@ -67,15 +67,16 @@ test_expect_success '1a-setup: Simple directory rename detection' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '1a-check: Simple directory rename detection' '
+test_expect_success '1a: Simple directory rename detection' '
+       test_setup_1a &&
        (
                cd 1a &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
 
                git ls-files -s >out &&
                test_line_count = 4 out &&
@@ -103,7 +104,7 @@ test_expect_success '1a-check: Simple directory rename detection' '
 #   Commit B: y/{b,c,d}
 #   Expected: y/{b,c,d,e}
 
-test_expect_success '1b-setup: Merge a directory with another' '
+test_setup_1b () {
        test_create_repo 1b &&
        (
                cd 1b &&
@@ -134,15 +135,16 @@ test_expect_success '1b-setup: Merge a directory with another' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '1b-check: Merge a directory with another' '
+test_expect_success '1b: Merge a directory with another' '
+       test_setup_1b &&
        (
                cd 1b &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 4 out &&
@@ -165,7 +167,7 @@ test_expect_success '1b-check: Merge a directory with another' '
 #   Commit B: z/{b,c,d}
 #   Expected: y/{b,c,d}  (because x/d -> z/d -> y/d)
 
-test_expect_success '1c-setup: Transitive renaming' '
+test_setup_1c () {
        test_create_repo 1c &&
        (
                cd 1c &&
@@ -193,15 +195,16 @@ test_expect_success '1c-setup: Transitive renaming' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '1c-check: Transitive renaming' '
+test_expect_success '1c: Transitive renaming' '
+       test_setup_1c &&
        (
                cd 1c &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
 
                git ls-files -s >out &&
                test_line_count = 3 out &&
@@ -227,7 +230,7 @@ test_expect_success '1c-check: Transitive renaming' '
 #   Note: y/m & z/n should definitely move into x.  By the same token, both
 #         y/wham_1 & z/wham_2 should too...giving us a conflict.
 
-test_expect_success '1d-setup: Directory renames cause a rename/rename(2to1) conflict' '
+test_setup_1d () {
        test_create_repo 1d &&
        (
                cd 1d &&
@@ -262,15 +265,16 @@ test_expect_success '1d-setup: Directory renames cause a rename/rename(2to1) con
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '1d-check: Directory renames cause a rename/rename(2to1) conflict' '
+test_expect_success '1d: Directory renames cause a rename/rename(2to1) conflict' '
+       test_setup_1d &&
        (
                cd 1d &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "CONFLICT (rename/rename)" out &&
 
                git ls-files -s >out &&
@@ -278,7 +282,7 @@ test_expect_success '1d-check: Directory renames cause a rename/rename(2to1) con
                git ls-files -u >out &&
                test_line_count = 2 out &&
                git ls-files -o >out &&
-               test_line_count = 3 out &&
+               test_line_count = 1 out &&
 
                git rev-parse >actual \
                        :0:x/b :0:x/c :0:x/d :0:x/e :0:x/m :0:x/n &&
@@ -293,15 +297,16 @@ test_expect_success '1d-check: Directory renames cause a rename/rename(2to1) con
                         A:y/wham  B:z/wham &&
                test_cmp expect actual &&
 
-               test_path_is_missing x/wham &&
-               test_path_is_file x/wham~HEAD &&
-               test_path_is_file x/wham~B^0 &&
-
-               git hash-object >actual \
-                       x/wham~HEAD x/wham~B^0 &&
-               git rev-parse >expect \
-                       A:y/wham    B:z/wham &&
-               test_cmp expect actual
+               # Test that the two-way merge in x/wham is as expected
+               git cat-file -p :2:x/wham >expect &&
+               git cat-file -p :3:x/wham >other &&
+               >empty &&
+               test_must_fail git merge-file \
+                       -L "HEAD" \
+                       -L "" \
+                       -L "B^0" \
+                       expect empty other &&
+               test_cmp expect x/wham
        )
 '
 
@@ -312,7 +317,7 @@ test_expect_success '1d-check: Directory renames cause a rename/rename(2to1) con
 #   Commit B: z/{oldb,oldc,d}
 #   Expected: y/{newb,newc,d}
 
-test_expect_success '1e-setup: Renamed directory, with all files being renamed too' '
+test_setup_1e () {
        test_create_repo 1e &&
        (
                cd 1e &&
@@ -341,15 +346,16 @@ test_expect_success '1e-setup: Renamed directory, with all files being renamed t
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '1e-check: Renamed directory, with all files being renamed too' '
+test_expect_success '1e: Renamed directory, with all files being renamed too' '
+       test_setup_1e &&
        (
                cd 1e &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 3 out &&
@@ -370,7 +376,7 @@ test_expect_success '1e-check: Renamed directory, with all files being renamed t
 #   Commit B: y/{b,c}, x/{d,e,f}
 #   Expected: y/{b,c}, x/{d,e,f,g}
 
-test_expect_success '1f-setup: Split a directory into two other directories' '
+test_setup_1f () {
        test_create_repo 1f &&
        (
                cd 1f &&
@@ -407,15 +413,16 @@ test_expect_success '1f-setup: Split a directory into two other directories' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '1f-check: Split a directory into two other directories' '
+test_expect_success '1f: Split a directory into two other directories' '
+       test_setup_1f &&
        (
                cd 1f &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 6 out &&
@@ -458,7 +465,7 @@ test_expect_success '1f-check: Split a directory into two other directories' '
 #   Commit A: y/b, w/c
 #   Commit B: z/{b,c,d}
 #   Expected: y/b, w/c, z/d, with warning about z/ -> (y/ vs. w/) conflict
-test_expect_success '2a-setup: Directory split into two on one side, with equal numbers of paths' '
+test_setup_2a () {
        test_create_repo 2a &&
        (
                cd 2a &&
@@ -488,15 +495,16 @@ test_expect_success '2a-setup: Directory split into two on one side, with equal
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '2a-check: Directory split into two on one side, with equal numbers of paths' '
+test_expect_success '2a: Directory split into two on one side, with equal numbers of paths' '
+       test_setup_2a &&
        (
                cd 2a &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "CONFLICT.*directory rename split" out &&
 
                git ls-files -s >out &&
@@ -519,7 +527,7 @@ test_expect_success '2a-check: Directory split into two on one side, with equal
 #   Commit A: y/b, w/c
 #   Commit B: z/{b,c}, x/d
 #   Expected: y/b, w/c, x/d; No warning about z/ -> (y/ vs. w/) conflict
-test_expect_success '2b-setup: Directory split into two on one side, with equal numbers of paths' '
+test_setup_2b () {
        test_create_repo 2b &&
        (
                cd 2b &&
@@ -550,15 +558,16 @@ test_expect_success '2b-setup: Directory split into two on one side, with equal
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '2b-check: Directory split into two on one side, with equal numbers of paths' '
+test_expect_success '2b: Directory split into two on one side, with equal numbers of paths' '
+       test_setup_2b &&
        (
                cd 2b &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 >out &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
 
                git ls-files -s >out &&
                test_line_count = 3 out &&
@@ -600,7 +609,7 @@ test_expect_success '2b-check: Directory split into two on one side, with equal
 #   Commit A: z/{b,c,d} (no change)
 #   Commit B: y/{b,c}, x/d
 #   Expected: y/{b,c}, x/d
-test_expect_success '3a-setup: Avoid implicit rename if involved as source on other side' '
+test_setup_3a () {
        test_create_repo 3a &&
        (
                cd 3a &&
@@ -631,15 +640,16 @@ test_expect_success '3a-setup: Avoid implicit rename if involved as source on ot
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '3a-check: Avoid implicit rename if involved as source on other side' '
+test_expect_success '3a: Avoid implicit rename if involved as source on other side' '
+       test_setup_3a &&
        (
                cd 3a &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 3 out &&
@@ -663,7 +673,7 @@ test_expect_success '3a-check: Avoid implicit rename if involved as source on ot
 #         get it involved in directory rename detection.  If it were, we might
 #         end up with CONFLICT:(z/d -> y/d vs. x/d vs. w/d), i.e. a
 #         rename/rename/rename(1to3) conflict, which is just weird.
-test_expect_success '3b-setup: Avoid implicit rename if involved as source on current side' '
+test_setup_3b () {
        test_create_repo 3b &&
        (
                cd 3b &&
@@ -696,15 +706,16 @@ test_expect_success '3b-setup: Avoid implicit rename if involved as source on cu
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '3b-check: Avoid implicit rename if involved as source on current side' '
+test_expect_success '3b: Avoid implicit rename if involved as source on current side' '
+       test_setup_3b &&
        (
                cd 3b &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep CONFLICT.*rename/rename.*z/d.*x/d.*w/d out &&
                test_i18ngrep ! CONFLICT.*rename/rename.*y/d out &&
 
@@ -743,7 +754,7 @@ test_expect_success '3b-check: Avoid implicit rename if involved as source on cu
 #
 # What if we were to attempt to do directory rename detection when someone
 # "mostly" moved a directory but still left some files around, or,
-# equivalently, fully renamed a directory in one commmit and then recreated
+# equivalently, fully renamed a directory in one commit and then recreated
 # that directory in a later commit adding some new files and then tried to
 # merge?
 #
@@ -785,7 +796,7 @@ test_expect_success '3b-check: Avoid implicit rename if involved as source on cu
 #   Expected: y/{b,c,d}, z/{e,f}
 #   NOTE: Even though most files from z moved to y, we don't want f to follow.
 
-test_expect_success '4a-setup: Directory split, with original directory still present' '
+test_setup_4a () {
        test_create_repo 4a &&
        (
                cd 4a &&
@@ -817,15 +828,16 @@ test_expect_success '4a-setup: Directory split, with original directory still pr
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '4a-check: Directory split, with original directory still present' '
+test_expect_success '4a: Directory split, with original directory still present' '
+       test_setup_4a &&
        (
                cd 4a &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 5 out &&
@@ -873,7 +885,7 @@ test_expect_success '4a-check: Directory split, with original directory still pr
 #         of history, giving us no way to represent this conflict in the
 #         index.
 
-test_expect_success '5a-setup: Merge directories, other side adds files to original and target' '
+test_setup_5a () {
        test_create_repo 5a &&
        (
                cd 5a &&
@@ -906,15 +918,16 @@ test_expect_success '5a-setup: Merge directories, other side adds files to origi
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '5a-check: Merge directories, other side adds files to original and target' '
+test_expect_success '5a: Merge directories, other side adds files to original and target' '
+       test_setup_5a &&
        (
                cd 5a &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "CONFLICT.*implicit dir rename" out &&
 
                git ls-files -s >out &&
@@ -940,14 +953,14 @@ test_expect_success '5a-check: Merge directories, other side adds files to origi
 #   Commit B: z/{b,c,d_1,e}, y/d_3
 #   Expected: y/{b,c,e}, CONFLICT(add/add: y/d_2 vs. y/d_3)
 #   NOTE: If z/d_1 in commit B were to be involved in dir rename detection, as
-#         we normaly would since z/ is being renamed to y/, then this would be
+#         we normally would since z/ is being renamed to y/, then this would be
 #         a rename/delete (z/d_1 -> y/d_1 vs. deleted) AND an add/add/add
 #         conflict of y/d_1 vs. y/d_2 vs. y/d_3.  Add/add/add is not
 #         representable in the index, so the existence of y/d_3 needs to
 #         cause us to bail on directory rename detection for that path, falling
 #         back to git behavior without the directory rename detection.
 
-test_expect_success '5b-setup: Rename/delete in order to get add/add/add conflict' '
+test_setup_5b () {
        test_create_repo 5b &&
        (
                cd 5b &&
@@ -980,15 +993,16 @@ test_expect_success '5b-setup: Rename/delete in order to get add/add/add conflic
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '5b-check: Rename/delete in order to get add/add/add conflict' '
+test_expect_success '5b: Rename/delete in order to get add/add/add conflict' '
+       test_setup_5b &&
        (
                cd 5b &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "CONFLICT (add/add).* y/d" out &&
 
                git ls-files -s >out &&
@@ -1023,7 +1037,7 @@ test_expect_success '5b-check: Rename/delete in order to get add/add/add conflic
 #             y/d are y/d_2 and y/d_4.  We still do the move from z/e to y/e,
 #             though, because it doesn't have anything in the way.
 
-test_expect_success '5c-setup: Transitive rename would cause rename/rename/rename/add/add/add' '
+test_setup_5c () {
        test_create_repo 5c &&
        (
                cd 5c &&
@@ -1060,15 +1074,16 @@ test_expect_success '5c-setup: Transitive rename would cause rename/rename/renam
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '5c-check: Transitive rename would cause rename/rename/rename/add/add/add' '
+test_expect_success '5c: Transitive rename would cause rename/rename/rename/add/add/add' '
+       test_setup_5c &&
        (
                cd 5c &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "CONFLICT (rename/rename).*x/d.*w/d.*z/d" out &&
                test_i18ngrep "CONFLICT (add/add).* y/d" out &&
 
@@ -1077,7 +1092,7 @@ test_expect_success '5c-check: Transitive rename would cause rename/rename/renam
                git ls-files -u >out &&
                test_line_count = 6 out &&
                git ls-files -o >out &&
-               test_line_count = 3 out &&
+               test_line_count = 1 out &&
 
                git rev-parse >actual \
                        :0:y/b :0:y/c :0:y/e &&
@@ -1093,9 +1108,9 @@ test_expect_success '5c-check: Transitive rename would cause rename/rename/renam
                test_cmp expect actual &&
 
                git hash-object >actual \
-                       w/d~HEAD w/d~B^0 z/d &&
+                       z/d &&
                git rev-parse >expect \
-                       O:x/d    B:w/d   O:x/d &&
+                       O:x/d &&
                test_cmp expect actual &&
                test_path_is_missing x/d &&
                test_path_is_file y/d &&
@@ -1112,7 +1127,7 @@ test_expect_success '5c-check: Transitive rename would cause rename/rename/renam
 #         detection for z/d_2, but that doesn't prevent us from applying the
 #         directory rename detection for z/f -> y/f.
 
-test_expect_success '5d-setup: Directory/file/file conflict due to directory rename' '
+test_setup_5d () {
        test_create_repo 5d &&
        (
                cd 5d &&
@@ -1144,15 +1159,16 @@ test_expect_success '5d-setup: Directory/file/file conflict due to directory ren
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '5d-check: Directory/file/file conflict due to directory rename' '
+test_expect_success '5d: Directory/file/file conflict due to directory rename' '
+       test_setup_5d &&
        (
                cd 5d &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "CONFLICT (file/directory).*y/d" out &&
 
                git ls-files -s >out &&
@@ -1204,7 +1220,7 @@ test_expect_success '5d-check: Directory/file/file conflict due to directory ren
 #         them under y/ doesn't accidentally catch z/d and make it look like
 #         it is also involved in a rename/delete conflict.
 
-test_expect_success '6a-setup: Tricky rename/delete' '
+test_setup_6a () {
        test_create_repo 6a &&
        (
                cd 6a &&
@@ -1234,15 +1250,16 @@ test_expect_success '6a-setup: Tricky rename/delete' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '6a-check: Tricky rename/delete' '
+test_expect_success '6a: Tricky rename/delete' '
+       test_setup_6a &&
        (
                cd 6a &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "CONFLICT (rename/delete).*z/c.*y/c" out &&
 
                git ls-files -s >out &&
@@ -1270,7 +1287,7 @@ test_expect_success '6a-check: Tricky rename/delete' '
 #         but B did that rename and still decided to put the file into z/,
 #         so we probably shouldn't apply directory rename detection for it.
 
-test_expect_success '6b-setup: Same rename done on both sides' '
+test_setup_6b () {
        test_create_repo 6b &&
        (
                cd 6b &&
@@ -1299,15 +1316,16 @@ test_expect_success '6b-setup: Same rename done on both sides' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '6b-check: Same rename done on both sides' '
+test_expect_success '6b: Same rename done on both sides' '
+       test_setup_6b &&
        (
                cd 6b &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 3 out &&
@@ -1333,7 +1351,7 @@ test_expect_success '6b-check: Same rename done on both sides' '
 #   NOTE: Seems obvious, but just checking that the implementation doesn't
 #         "accidentally detect a rename" and give us y/{b,c,d}.
 
-test_expect_success '6c-setup: Rename only done on same side' '
+test_setup_6c () {
        test_create_repo 6c &&
        (
                cd 6c &&
@@ -1361,15 +1379,16 @@ test_expect_success '6c-setup: Rename only done on same side' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '6c-check: Rename only done on same side' '
+test_expect_success '6c: Rename only done on same side' '
+       test_setup_6c &&
        (
                cd 6c &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 3 out &&
@@ -1395,7 +1414,7 @@ test_expect_success '6c-check: Rename only done on same side' '
 #   NOTE: Again, this seems obvious but just checking that the implementation
 #         doesn't "accidentally detect a rename" and give us y/{b,c,d}.
 
-test_expect_success '6d-setup: We do not always want transitive renaming' '
+test_setup_6d () {
        test_create_repo 6d &&
        (
                cd 6d &&
@@ -1423,15 +1442,16 @@ test_expect_success '6d-setup: We do not always want transitive renaming' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '6d-check: We do not always want transitive renaming' '
+test_expect_success '6d: We do not always want transitive renaming' '
+       test_setup_6d &&
        (
                cd 6d &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 3 out &&
@@ -1457,7 +1477,7 @@ test_expect_success '6d-check: We do not always want transitive renaming' '
 #         doesn't "accidentally detect a rename" and give us y/{b,c} +
 #         add/add conflict on y/d_1 vs y/d_2.
 
-test_expect_success '6e-setup: Add/add from one side' '
+test_setup_6e () {
        test_create_repo 6e &&
        (
                cd 6e &&
@@ -1486,15 +1506,16 @@ test_expect_success '6e-setup: Add/add from one side' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '6e-check: Add/add from one side' '
+test_expect_success '6e: Add/add from one side' '
+       test_setup_6e &&
        (
                cd 6e &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 4 out &&
@@ -1551,7 +1572,7 @@ test_expect_success '6e-check: Add/add from one side' '
 #   Expected: y/d, CONFLICT(rename/rename for both z/b and z/c)
 #   NOTE: There's a rename of z/ here, y/ has more renames, so z/d -> y/d.
 
-test_expect_success '7a-setup: rename-dir vs. rename-dir (NOT split evenly) PLUS add-other-file' '
+test_setup_7a () {
        test_create_repo 7a &&
        (
                cd 7a &&
@@ -1582,15 +1603,16 @@ test_expect_success '7a-setup: rename-dir vs. rename-dir (NOT split evenly) PLUS
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '7a-check: rename-dir vs. rename-dir (NOT split evenly) PLUS add-other-file' '
+test_expect_success '7a: rename-dir vs. rename-dir (NOT split evenly) PLUS add-other-file' '
+       test_setup_7a &&
        (
                cd 7a &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "CONFLICT (rename/rename).*z/b.*y/b.*w/b" out &&
                test_i18ngrep "CONFLICT (rename/rename).*z/c.*y/c.*x/c" out &&
 
@@ -1622,7 +1644,7 @@ test_expect_success '7a-check: rename-dir vs. rename-dir (NOT split evenly) PLUS
 #   Commit B: z/{b,c,d_1},        w/d_2
 #   Expected: y/{b,c}, CONFLICT(rename/rename(2to1): x/d_1, w/d_2 -> y_d)
 
-test_expect_success '7b-setup: rename/rename(2to1), but only due to transitive rename' '
+test_setup_7b () {
        test_create_repo 7b &&
        (
                cd 7b &&
@@ -1654,15 +1676,16 @@ test_expect_success '7b-setup: rename/rename(2to1), but only due to transitive r
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '7b-check: rename/rename(2to1), but only due to transitive rename' '
+test_expect_success '7b: rename/rename(2to1), but only due to transitive rename' '
+       test_setup_7b &&
        (
                cd 7b &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "CONFLICT (rename/rename)" out &&
 
                git ls-files -s >out &&
@@ -1670,7 +1693,7 @@ test_expect_success '7b-check: rename/rename(2to1), but only due to transitive r
                git ls-files -u >out &&
                test_line_count = 2 out &&
                git ls-files -o >out &&
-               test_line_count = 3 out &&
+               test_line_count = 1 out &&
 
                git rev-parse >actual \
                        :0:y/b :0:y/c :2:y/d :3:y/d &&
@@ -1678,15 +1701,16 @@ test_expect_success '7b-check: rename/rename(2to1), but only due to transitive r
                         O:z/b  O:z/c  O:w/d  O:x/d &&
                test_cmp expect actual &&
 
-               test_path_is_missing y/d &&
-               test_path_is_file y/d~HEAD &&
-               test_path_is_file y/d~B^0 &&
-
-               git hash-object >actual \
-                       y/d~HEAD y/d~B^0 &&
-               git rev-parse >expect \
-                       O:w/d    O:x/d &&
-               test_cmp expect actual
+               # Test that the two-way merge in y/d is as expected
+               git cat-file -p :2:y/d >expect &&
+               git cat-file -p :3:y/d >other &&
+               >empty &&
+               test_must_fail git merge-file \
+                       -L "HEAD" \
+                       -L "" \
+                       -L "B^0" \
+                       expect empty other &&
+               test_cmp expect y/d
        )
 '
 
@@ -1700,7 +1724,7 @@ test_expect_success '7b-check: rename/rename(2to1), but only due to transitive r
 #         neither CONFLICT(x/d -> w/d vs. z/d)
 #         nor CONFLiCT x/d -> w/d vs. y/d vs. z/d)
 
-test_expect_success '7c-setup: rename/rename(1to...2or3); transitive rename may add complexity' '
+test_setup_7c () {
        test_create_repo 7c &&
        (
                cd 7c &&
@@ -1730,15 +1754,16 @@ test_expect_success '7c-setup: rename/rename(1to...2or3); transitive rename may
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '7c-check: rename/rename(1to...2or3); transitive rename may add complexity' '
+test_expect_success '7c: rename/rename(1to...2or3); transitive rename may add complexity' '
+       test_setup_7c &&
        (
                cd 7c &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "CONFLICT (rename/rename).*x/d.*w/d.*y/d" out &&
 
                git ls-files -s >out &&
@@ -1764,7 +1789,7 @@ test_expect_success '7c-check: rename/rename(1to...2or3); transitive rename may
 #   Expected: y/{b,c}, CONFLICT(delete x/d vs rename to y/d)
 #   NOTE: z->y so NOT CONFLICT(delete x/d vs rename to z/d)
 
-test_expect_success '7d-setup: transitive rename involved in rename/delete; how is it reported?' '
+test_setup_7d () {
        test_create_repo 7d &&
        (
                cd 7d &&
@@ -1794,15 +1819,16 @@ test_expect_success '7d-setup: transitive rename involved in rename/delete; how
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '7d-check: transitive rename involved in rename/delete; how is it reported?' '
+test_expect_success '7d: transitive rename involved in rename/delete; how is it reported?' '
+       test_setup_7d &&
        (
                cd 7d &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "CONFLICT (rename/delete).*x/d.*y/d" out &&
 
                git ls-files -s >out &&
@@ -1849,7 +1875,7 @@ test_expect_success '7d-check: transitive rename involved in rename/delete; how
 #         see testcases 9c and 9d for further discussion of this issue and
 #         how it's resolved.
 
-test_expect_success '7e-setup: transitive rename in rename/delete AND dirs in the way' '
+test_setup_7e () {
        test_create_repo 7e &&
        (
                cd 7e &&
@@ -1884,15 +1910,16 @@ test_expect_success '7e-setup: transitive rename in rename/delete AND dirs in th
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '7e-check: transitive rename in rename/delete AND dirs in the way' '
+test_expect_success '7e: transitive rename in rename/delete AND dirs in the way' '
+       test_setup_7e &&
        (
                cd 7e &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "CONFLICT (rename/delete).*x/d.*y/d" out &&
 
                git ls-files -s >out &&
@@ -1943,7 +1970,7 @@ test_expect_success '7e-check: transitive rename in rename/delete AND dirs in th
 # simple rule from section 5 prevents me from handling this as optimally as
 # we potentially could.
 
-test_expect_success '8a-setup: Dual-directory rename, one into the others way' '
+test_setup_8a () {
        test_create_repo 8a &&
        (
                cd 8a &&
@@ -1975,15 +2002,16 @@ test_expect_success '8a-setup: Dual-directory rename, one into the others way' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '8a-check: Dual-directory rename, one into the others way' '
+test_expect_success '8a: Dual-directory rename, one into the others way' '
+       test_setup_8a &&
        (
                cd 8a &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 6 out &&
@@ -2021,7 +2049,7 @@ test_expect_success '8a-check: Dual-directory rename, one into the others way' '
 # making us fall back to pre-directory-rename-detection behavior for both
 # e_1 and e_2.
 
-test_expect_success '8b-setup: Dual-directory rename, one into the others way, with conflicting filenames' '
+test_setup_8b () {
        test_create_repo 8b &&
        (
                cd 8b &&
@@ -2053,15 +2081,16 @@ test_expect_success '8b-setup: Dual-directory rename, one into the others way, w
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '8b-check: Dual-directory rename, one into the others way, with conflicting filenames' '
+test_expect_success '8b: Dual-directory rename, one into the others way, with conflicting filenames' '
+       test_setup_8b &&
        (
                cd 8b &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 6 out &&
@@ -2087,14 +2116,14 @@ test_expect_success '8b-check: Dual-directory rename, one into the others way, w
 #
 #   Note: It could easily be argued that the correct resolution here is
 #         y/{b,c,e}, CONFLICT(rename/delete: z/d -> y/d vs deleted)
-#         and that the modifed version of d should be present in y/ after
+#         and that the modified version of d should be present in y/ after
 #         the merge, just marked as conflicted.  Indeed, I previously did
 #         argue that.  But applying directory renames to the side of
 #         history where a file is merely modified results in spurious
 #         rename/rename(1to2) conflicts -- see testcase 9h.  See also
 #         notes in 8d.
 
-test_expect_success '8c-setup: modify/delete or rename+modify/delete?' '
+test_setup_8c () {
        test_create_repo 8c &&
        (
                cd 8c &&
@@ -2125,15 +2154,16 @@ test_expect_success '8c-setup: modify/delete or rename+modify/delete?' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '8c-check: modify/delete or rename+modify/delete' '
+test_expect_success '8c: modify/delete or rename+modify/delete' '
+       test_setup_8c &&
        (
                cd 8c &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "CONFLICT (modify/delete).* z/d" out &&
 
                git ls-files -s >out &&
@@ -2173,7 +2203,7 @@ test_expect_success '8c-check: modify/delete or rename+modify/delete' '
 #   during merging are supposed to be about opposite sides doing things
 #   differently.
 
-test_expect_success '8d-setup: rename/delete...or not?' '
+test_setup_8d () {
        test_create_repo 8d &&
        (
                cd 8d &&
@@ -2202,15 +2232,16 @@ test_expect_success '8d-setup: rename/delete...or not?' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '8d-check: rename/delete...or not?' '
+test_expect_success '8d: rename/delete...or not?' '
+       test_setup_8d &&
        (
                cd 8d &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 3 out &&
@@ -2248,7 +2279,7 @@ test_expect_success '8d-check: rename/delete...or not?' '
 #        about the ramifications of doing that, I didn't know how to rule out
 #        that opening other weird edge and corner cases so I just punted.
 
-test_expect_success '8e-setup: Both sides rename, one side adds to original directory' '
+test_setup_8e () {
        test_create_repo 8e &&
        (
                cd 8e &&
@@ -2277,15 +2308,16 @@ test_expect_success '8e-setup: Both sides rename, one side adds to original dire
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '8e-check: Both sides rename, one side adds to original directory' '
+test_expect_success '8e: Both sides rename, one side adds to original directory' '
+       test_setup_8e &&
        (
                cd 8e &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out 2>err &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
                test_i18ngrep CONFLICT.*rename/rename.*z/c.*y/c.*w/c out &&
                test_i18ngrep CONFLICT.*rename/rename.*z/b.*y/b.*w/b out &&
 
@@ -2331,7 +2363,7 @@ test_expect_success '8e-check: Both sides rename, one side adds to original dire
 #         of which one had the most paths going to it.  A naive implementation
 #         of that could take the new file in commit B at z/i to x/w/i or x/i.
 
-test_expect_success '9a-setup: Inner renamed directory within outer renamed directory' '
+test_setup_9a () {
        test_create_repo 9a &&
        (
                cd 9a &&
@@ -2364,15 +2396,16 @@ test_expect_success '9a-setup: Inner renamed directory within outer renamed dire
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '9a-check: Inner renamed directory within outer renamed directory' '
+test_expect_success '9a: Inner renamed directory within outer renamed directory' '
+       test_setup_9a &&
        (
                cd 9a &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 7 out &&
@@ -2402,7 +2435,7 @@ test_expect_success '9a-check: Inner renamed directory within outer renamed dire
 #   Commit B: z/{b,c,d_3}
 #   Expected: y/{b,c,d_merged}
 
-test_expect_success '9b-setup: Transitive rename with content merge' '
+test_setup_9b () {
        test_create_repo 9b &&
        (
                cd 9b &&
@@ -2434,15 +2467,16 @@ test_expect_success '9b-setup: Transitive rename with content merge' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '9b-check: Transitive rename with content merge' '
+test_expect_success '9b: Transitive rename with content merge' '
+       test_setup_9b &&
        (
                cd 9b &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 3 out &&
@@ -2489,7 +2523,7 @@ test_expect_success '9b-check: Transitive rename with content merge' '
 #         away, then ignore that particular rename from the other side of
 #         history for any implicit directory renames.
 
-test_expect_success '9c-setup: Doubly transitive rename?' '
+test_setup_9c () {
        test_create_repo 9c &&
        (
                cd 9c &&
@@ -2524,15 +2558,16 @@ test_expect_success '9c-setup: Doubly transitive rename?' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '9c-check: Doubly transitive rename?' '
+test_expect_success '9c: Doubly transitive rename?' '
+       test_setup_9c &&
        (
                cd 9c &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 >out &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "WARNING: Avoiding applying x -> z rename to x/f" out &&
 
                git ls-files -s >out &&
@@ -2577,7 +2612,7 @@ test_expect_success '9c-check: Doubly transitive rename?' '
 #   simple rules that are consistent with what we need for all the other
 #   testcases and simplifies things for the user.
 
-test_expect_success '9d-setup: N-way transitive rename?' '
+test_setup_9d () {
        test_create_repo 9d &&
        (
                cd 9d &&
@@ -2612,15 +2647,16 @@ test_expect_success '9d-setup: N-way transitive rename?' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '9d-check: N-way transitive rename?' '
+test_expect_success '9d: N-way transitive rename?' '
+       test_setup_9d &&
        (
                cd 9d &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 >out &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                test_i18ngrep "WARNING: Avoiding applying z -> y rename to z/t" out &&
                test_i18ngrep "WARNING: Avoiding applying y -> x rename to y/a" out &&
                test_i18ngrep "WARNING: Avoiding applying x -> w rename to x/b" out &&
@@ -2651,7 +2687,7 @@ test_expect_success '9d-check: N-way transitive rename?' '
 #   Expected: combined/{a,b,c,d,e,f,g,h,i,j,k,l}, CONFLICT(Nto1) warnings,
 #             dir1/yo, dir2/yo, dir3/yo, dirN/yo
 
-test_expect_success '9e-setup: N-to-1 whammo' '
+test_setup_9e () {
        test_create_repo 9e &&
        (
                cd 9e &&
@@ -2694,15 +2730,16 @@ test_expect_success '9e-setup: N-to-1 whammo' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success C_LOCALE_OUTPUT '9e-check: N-to-1 whammo' '
+test_expect_success C_LOCALE_OUTPUT '9e: N-to-1 whammo' '
+       test_setup_9e &&
        (
                cd 9e &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 >out &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
                grep "CONFLICT (implicit dir rename): Cannot map more than one path to combined/yo" out >error_line &&
                grep -q dir1/yo error_line &&
                grep -q dir2/yo error_line &&
@@ -2743,7 +2780,7 @@ test_expect_success C_LOCALE_OUTPUT '9e-check: N-to-1 whammo' '
 #   Commit B: goal/{a,b}/$more_files, goal/c
 #   Expected: priority/{a,b}/$more_files, priority/c
 
-test_expect_success '9f-setup: Renamed directory that only contained immediate subdirs' '
+test_setup_9f () {
        test_create_repo 9f &&
        (
                cd 9f &&
@@ -2772,15 +2809,16 @@ test_expect_success '9f-setup: Renamed directory that only contained immediate s
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '9f-check: Renamed directory that only contained immediate subdirs' '
+test_expect_success '9f: Renamed directory that only contained immediate subdirs' '
+       test_setup_9f &&
        (
                cd 9f &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 4 out &&
@@ -2807,7 +2845,7 @@ test_expect_success '9f-check: Renamed directory that only contained immediate s
 #   Commit B: goal/{a,b}/$more_files, goal/c
 #   Expected: priority/{alpha,bravo}/$more_files, priority/c
 
-test_expect_success '9g-setup: Renamed directory that only contained immediate subdirs, immediate subdirs renamed' '
+test_setup_9g () {
        test_create_repo 9g &&
        (
                cd 9g &&
@@ -2839,15 +2877,15 @@ test_expect_success '9g-setup: Renamed directory that only contained immediate s
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_failure '9g-check: Renamed directory that only contained immediate subdirs, immediate subdirs renamed' '
+test_expect_failure '9g: Renamed directory that only contained immediate subdirs, immediate subdirs renamed' '
        (
                cd 9g &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 4 out &&
@@ -2875,7 +2913,7 @@ test_expect_failure '9g-check: Renamed directory that only contained immediate s
 #   Expected: y/{b,c}, x/d_2
 #   NOTE: If we applied the z/ -> y/ rename to z/d, then we'd end up with
 #         a rename/rename(1to2) conflict (z/d -> y/d vs. x/d)
-test_expect_success '9h-setup: Avoid dir rename on merely modified path' '
+test_setup_9h () {
        test_create_repo 9h &&
        (
                cd 9h &&
@@ -2908,15 +2946,16 @@ test_expect_success '9h-setup: Avoid dir rename on merely modified path' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '9h-check: Avoid dir rename on merely modified path' '
+test_expect_success '9h: Avoid dir rename on merely modified path' '
+       test_setup_9h &&
        (
                cd 9h &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 3 out &&
@@ -2955,7 +2994,7 @@ test_expect_success '9h-check: Avoid dir rename on merely modified path' '
 #   Expected: Aborted Merge +
 #       ERROR_MSG(untracked working tree files would be overwritten by merge)
 
-test_expect_success '10a-setup: Overwrite untracked with normal rename/delete' '
+test_setup_10a () {
        test_create_repo 10a &&
        (
                cd 10a &&
@@ -2981,9 +3020,10 @@ test_expect_success '10a-setup: Overwrite untracked with normal rename/delete' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '10a-check: Overwrite untracked with normal rename/delete' '
+test_expect_success '10a: Overwrite untracked with normal rename/delete' '
+       test_setup_10a &&
        (
                cd 10a &&
 
@@ -2991,7 +3031,7 @@ test_expect_success '10a-check: Overwrite untracked with normal rename/delete' '
                echo very >z/c &&
                echo important >z/d &&
 
-               test_must_fail git merge -s recursive B^0 >out 2>err &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
                test_i18ngrep "The following untracked working tree files would be overwritten by merge" err &&
 
                git ls-files -s >out &&
@@ -3019,7 +3059,7 @@ test_expect_success '10a-check: Overwrite untracked with normal rename/delete' '
 #             z/c_1 -> z/d_1 rename recorded at stage 3 for y/d +
 #       ERROR_MSG(refusing to lose untracked file at 'y/d')
 
-test_expect_success '10b-setup: Overwrite untracked with dir rename + delete' '
+test_setup_10b () {
        test_create_repo 10b &&
        (
                cd 10b &&
@@ -3048,9 +3088,10 @@ test_expect_success '10b-setup: Overwrite untracked with dir rename + delete' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '10b-check: Overwrite untracked with dir rename + delete' '
+test_expect_success '10b: Overwrite untracked with dir rename + delete' '
+       test_setup_10b &&
        (
                cd 10b &&
 
@@ -3059,7 +3100,7 @@ test_expect_success '10b-check: Overwrite untracked with dir rename + delete' '
                echo important >y/d &&
                echo contents >y/e &&
 
-               test_must_fail git merge -s recursive B^0 >out 2>err &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
                test_i18ngrep "CONFLICT (rename/delete).*Version B\^0 of y/d left in tree at y/d~B\^0" out &&
                test_i18ngrep "Error: Refusing to lose untracked file at y/e; writing to y/e~B\^0 instead" out &&
 
@@ -3096,10 +3137,10 @@ test_expect_success '10b-check: Overwrite untracked with dir rename + delete' '
 #             y/c~B^0 +
 #             ERROR_MSG(Refusing to lose untracked file at y/c)
 
-test_expect_success '10c-setup: Overwrite untracked with dir rename/rename(1to2)' '
-       test_create_repo 10c &&
+test_setup_10c () {
+       test_create_repo 10c_$1 &&
        (
-               cd 10c &&
+               cd 10c_$1 &&
 
                mkdir z x &&
                echo a >z/a &&
@@ -3126,16 +3167,17 @@ test_expect_success '10c-setup: Overwrite untracked with dir rename/rename(1to2)
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '10c-check: Overwrite untracked with dir rename/rename(1to2)' '
+test_expect_success '10c1: Overwrite untracked with dir rename/rename(1to2)' '
+       test_setup_10c 1 &&
        (
-               cd 10c &&
+               cd 10c_1 &&
 
                git checkout A^0 &&
                echo important >y/c &&
 
-               test_must_fail git merge -s recursive B^0 >out 2>err &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
                test_i18ngrep "CONFLICT (rename/rename)" out &&
                test_i18ngrep "Refusing to lose untracked file at y/c; adding as y/c~B\^0 instead" out &&
 
@@ -3161,15 +3203,53 @@ test_expect_success '10c-check: Overwrite untracked with dir rename/rename(1to2)
        )
 '
 
+test_expect_success '10c2: Overwrite untracked with dir rename/rename(1to2), other direction' '
+       test_setup_10c 2 &&
+       (
+               cd 10c_2 &&
+
+               git reset --hard &&
+               git clean -fdqx &&
+
+               git checkout B^0 &&
+               mkdir y &&
+               echo important >y/c &&
+
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err &&
+               test_i18ngrep "CONFLICT (rename/rename)" out &&
+               test_i18ngrep "Refusing to lose untracked file at y/c; adding as y/c~HEAD instead" out &&
+
+               git ls-files -s >out &&
+               test_line_count = 6 out &&
+               git ls-files -u >out &&
+               test_line_count = 3 out &&
+               git ls-files -o >out &&
+               test_line_count = 3 out &&
+
+               git rev-parse >actual \
+                       :0:y/a :0:y/b :0:x/d :1:x/c :3:w/c :2:y/c &&
+               git rev-parse >expect \
+                        O:z/a  O:z/b  O:x/d  O:x/c  O:x/c  O:x/c &&
+               test_cmp expect actual &&
+
+               git hash-object y/c~HEAD >actual &&
+               git rev-parse O:x/c >expect &&
+               test_cmp expect actual &&
+
+               echo important >expect &&
+               test_cmp expect y/c
+       )
+'
+
 # Testcase 10d, Delete untracked w/ dir rename/rename(2to1)
 #   Commit O: z/{a,b,c_1},        x/{d,e,f_2}
 #   Commit A: y/{a,b},            x/{d,e,f_2,wham_1} + untracked y/wham
 #   Commit B: z/{a,b,c_1,wham_2}, y/{d,e}
-#   Expected: Failed Merge; y/{a,b,d,e} + untracked y/{wham,wham~B^0,wham~HEAD}+
+#   Expected: Failed Merge; y/{a,b,d,e} + untracked y/{wham,wham~merged}+
 #             CONFLICT(rename/rename) z/c_1 vs x/f_2 -> y/wham
 #             ERROR_MSG(Refusing to lose untracked file at y/wham)
 
-test_expect_success '10d-setup: Delete untracked with dir rename/rename(2to1)' '
+test_setup_10d () {
        test_create_repo 10d &&
        (
                cd 10d &&
@@ -3201,16 +3281,17 @@ test_expect_success '10d-setup: Delete untracked with dir rename/rename(2to1)' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '10d-check: Delete untracked with dir rename/rename(2to1)' '
+test_expect_success '10d: Delete untracked with dir rename/rename(2to1)' '
+       test_setup_10d &&
        (
                cd 10d &&
 
                git checkout A^0 &&
                echo important >y/wham &&
 
-               test_must_fail git merge -s recursive B^0 >out 2>err &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
                test_i18ngrep "CONFLICT (rename/rename)" out &&
                test_i18ngrep "Refusing to lose untracked file at y/wham" out &&
 
@@ -3219,7 +3300,7 @@ test_expect_success '10d-check: Delete untracked with dir rename/rename(2to1)' '
                git ls-files -u >out &&
                test_line_count = 2 out &&
                git ls-files -o >out &&
-               test_line_count = 4 out &&
+               test_line_count = 3 out &&
 
                git rev-parse >actual \
                        :0:y/a :0:y/b :0:y/d :0:y/e :2:y/wham :3:y/wham &&
@@ -3232,11 +3313,16 @@ test_expect_success '10d-check: Delete untracked with dir rename/rename(2to1)' '
                echo important >expect &&
                test_cmp expect y/wham &&
 
-               git hash-object >actual \
-                       y/wham~B^0 y/wham~HEAD &&
-               git rev-parse >expect \
-                       O:x/f      O:z/c &&
-               test_cmp expect actual
+               # Test that the two-way merge in y/wham~merged is as expected
+               git cat-file -p :2:y/wham >expect &&
+               git cat-file -p :3:y/wham >other &&
+               >empty &&
+               test_must_fail git merge-file \
+                       -L "HEAD" \
+                       -L "" \
+                       -L "B^0" \
+                       expect empty other &&
+               test_cmp expect y/wham~merged
        )
 '
 
@@ -3246,7 +3332,7 @@ test_expect_success '10d-check: Delete untracked with dir rename/rename(2to1)' '
 #   Commit B: z/{a,b,c}
 #   Expected: y/{a,b,c} + untracked z/c
 
-test_expect_success '10e-setup: Does git complain about untracked file that is not really in the way?' '
+test_setup_10e () {
        test_create_repo 10e &&
        (
                cd 10e &&
@@ -3273,9 +3359,9 @@ test_expect_success '10e-setup: Does git complain about untracked file that is n
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_failure '10e-check: Does git complain about untracked file that is not really in the way?' '
+test_expect_failure '10e: Does git complain about untracked file that is not really in the way?' '
        (
                cd 10e &&
 
@@ -3283,7 +3369,7 @@ test_expect_failure '10e-check: Does git complain about untracked file that is n
                mkdir z &&
                echo random >z/c &&
 
-               git merge -s recursive B^0 >out 2>err &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
                test_i18ngrep ! "following untracked working tree files would be overwritten by merge" err &&
 
                git ls-files -s >out &&
@@ -3327,7 +3413,7 @@ test_expect_failure '10e-check: Does git complain about untracked file that is n
 #             z/c~HEAD with contents of B:z/b_v2,
 #             z/c with uncommitted mods on top of A:z/c_v1
 
-test_expect_success '11a-setup: Avoid losing dirty contents with simple rename' '
+test_setup_11a () {
        test_create_repo 11a &&
        (
                cd 11a &&
@@ -3354,16 +3440,17 @@ test_expect_success '11a-setup: Avoid losing dirty contents with simple rename'
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '11a-check: Avoid losing dirty contents with simple rename' '
+test_expect_success '11a: Avoid losing dirty contents with simple rename' '
+       test_setup_11a &&
        (
                cd 11a &&
 
                git checkout A^0 &&
                echo stuff >>z/c &&
 
-               test_must_fail git merge -s recursive B^0 >out 2>err &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
                test_i18ngrep "Refusing to lose dirty file at z/c" out &&
 
                test_seq 1 10 >expected &&
@@ -3397,7 +3484,7 @@ test_expect_success '11a-check: Avoid losing dirty contents with simple rename'
 #             ERROR_MSG(Refusing to lose dirty file at z/c)
 
 
-test_expect_success '11b-setup: Avoid losing dirty file involved in directory rename' '
+test_setup_11b () {
        test_create_repo 11b &&
        (
                cd 11b &&
@@ -3426,16 +3513,17 @@ test_expect_success '11b-setup: Avoid losing dirty file involved in directory re
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '11b-check: Avoid losing dirty file involved in directory rename' '
+test_expect_success '11b: Avoid losing dirty file involved in directory rename' '
+       test_setup_11b &&
        (
                cd 11b &&
 
                git checkout A^0 &&
                echo stuff >>z/c &&
 
-               git merge -s recursive B^0 >out 2>err &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
                test_i18ngrep "Refusing to lose dirty file at z/c" out &&
 
                grep -q stuff z/c &&
@@ -3471,7 +3559,7 @@ test_expect_success '11b-check: Avoid losing dirty file involved in directory re
 #   Expected: Abort_msg("following files would be overwritten by merge") +
 #             y/c left untouched (still has uncommitted mods)
 
-test_expect_success '11c-setup: Avoid losing not-uptodate with rename + D/F conflict' '
+test_setup_11c () {
        test_create_repo 11c &&
        (
                cd 11c &&
@@ -3501,16 +3589,17 @@ test_expect_success '11c-setup: Avoid losing not-uptodate with rename + D/F conf
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '11c-check: Avoid losing not-uptodate with rename + D/F conflict' '
+test_expect_success '11c: Avoid losing not-uptodate with rename + D/F conflict' '
+       test_setup_11c &&
        (
                cd 11c &&
 
                git checkout A^0 &&
                echo stuff >>y/c &&
 
-               test_must_fail git merge -s recursive B^0 >out 2>err &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
                test_i18ngrep "following files would be overwritten by merge" err &&
 
                grep -q stuff y/c &&
@@ -3537,7 +3626,7 @@ test_expect_success '11c-check: Avoid losing not-uptodate with rename + D/F conf
 #             Warning_Msg("Refusing to lose dirty file at z/c) +
 #             y/{a,c~HEAD,c/d}, x/b, now-untracked z/c_v1 with uncommitted mods
 
-test_expect_success '11d-setup: Avoid losing not-uptodate with rename + D/F conflict' '
+test_setup_11d () {
        test_create_repo 11d &&
        (
                cd 11d &&
@@ -3568,16 +3657,17 @@ test_expect_success '11d-setup: Avoid losing not-uptodate with rename + D/F conf
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '11d-check: Avoid losing not-uptodate with rename + D/F conflict' '
+test_expect_success '11d: Avoid losing not-uptodate with rename + D/F conflict' '
+       test_setup_11d &&
        (
                cd 11d &&
 
                git checkout A^0 &&
                echo stuff >>z/c &&
 
-               test_must_fail git merge -s recursive B^0 >out 2>err &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
                test_i18ngrep "Refusing to lose dirty file at z/c" out &&
 
                grep -q stuff z/c &&
@@ -3615,7 +3705,7 @@ test_expect_success '11d-check: Avoid losing not-uptodate with rename + D/F conf
 #             y/c~HEAD has A:y/c_2 contents
 #             y/c has dirty file from before merge
 
-test_expect_success '11e-setup: Avoid deleting not-uptodate with dir rename/rename(1to2)/add' '
+test_setup_11e () {
        test_create_repo 11e &&
        (
                cd 11e &&
@@ -3647,16 +3737,17 @@ test_expect_success '11e-setup: Avoid deleting not-uptodate with dir rename/rena
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '11e-check: Avoid deleting not-uptodate with dir rename/rename(1to2)/add' '
+test_expect_success '11e: Avoid deleting not-uptodate with dir rename/rename(1to2)/add' '
+       test_setup_11e &&
        (
                cd 11e &&
 
                git checkout A^0 &&
                echo mods >>y/c &&
 
-               test_must_fail git merge -s recursive B^0 >out 2>err &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
                test_i18ngrep "CONFLICT (rename/rename)" out &&
                test_i18ngrep "Refusing to lose dirty file at y/c" out &&
 
@@ -3665,7 +3756,7 @@ test_expect_success '11e-check: Avoid deleting not-uptodate with dir rename/rena
                git ls-files -u >out &&
                test_line_count = 4 out &&
                git ls-files -o >out &&
-               test_line_count = 4 out &&
+               test_line_count = 3 out &&
 
                echo different >expected &&
                echo mods >>expected &&
@@ -3677,11 +3768,17 @@ test_expect_success '11e-check: Avoid deleting not-uptodate with dir rename/rena
                         O:z/a  O:z/b  O:x/d  O:x/c  O:x/c  A:y/c  O:x/c &&
                test_cmp expect actual &&
 
-               git hash-object >actual \
-                       y/c~B^0 y/c~HEAD &&
-               git rev-parse >expect \
-                       O:x/c   A:y/c &&
-               test_cmp expect actual
+               # See if y/c~merged has expected contents; requires manually
+               # doing the expected file merge
+               git cat-file -p A:y/c >c1 &&
+               git cat-file -p B:z/c >c2 &&
+               >empty &&
+               test_must_fail git merge-file \
+                       -L "HEAD" \
+                       -L "" \
+                       -L "B^0" \
+                       c1 empty c2 &&
+               test_cmp c1 y/c~merged
        )
 '
 
@@ -3689,12 +3786,12 @@ test_expect_success '11e-check: Avoid deleting not-uptodate with dir rename/rena
 #   Commit O: z/{a,b},        x/{c_1,d_2}
 #   Commit A: y/{a,b,wham_1}, x/d_2, except y/wham has uncommitted mods
 #   Commit B: z/{a,b,wham_2}, x/c_1
-#   Expected: Failed Merge; y/{a,b} + untracked y/{wham~B^0,wham~B^HEAD} +
+#   Expected: Failed Merge; y/{a,b} + untracked y/{wham~merged} +
 #             y/wham with dirty changes from before merge +
 #             CONFLICT(rename/rename) x/c vs x/d -> y/wham
 #             ERROR_MSG(Refusing to lose dirty file at y/wham)
 
-test_expect_success '11f-setup: Avoid deleting not-uptodate with dir rename/rename(2to1)' '
+test_setup_11f () {
        test_create_repo 11f &&
        (
                cd 11f &&
@@ -3723,16 +3820,17 @@ test_expect_success '11f-setup: Avoid deleting not-uptodate with dir rename/rena
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '11f-check: Avoid deleting not-uptodate with dir rename/rename(2to1)' '
+test_expect_success '11f: Avoid deleting not-uptodate with dir rename/rename(2to1)' '
+       test_setup_11f &&
        (
                cd 11f &&
 
                git checkout A^0 &&
                echo important >>y/wham &&
 
-               test_must_fail git merge -s recursive B^0 >out 2>err &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
                test_i18ngrep "CONFLICT (rename/rename)" out &&
                test_i18ngrep "Refusing to lose dirty file at y/wham" out &&
 
@@ -3741,24 +3839,30 @@ test_expect_success '11f-check: Avoid deleting not-uptodate with dir rename/rena
                git ls-files -u >out &&
                test_line_count = 2 out &&
                git ls-files -o >out &&
-               test_line_count = 4 out &&
+               test_line_count = 3 out &&
 
                test_seq 1 10 >expected &&
                echo important >>expected &&
                test_cmp expected y/wham &&
 
                test_must_fail git rev-parse :1:y/wham &&
-               git hash-object >actual \
-                       y/wham~B^0 y/wham~HEAD &&
-               git rev-parse >expect \
-                       O:x/d      O:x/c &&
-               test_cmp expect actual &&
 
                git rev-parse >actual \
                        :0:y/a :0:y/b :2:y/wham :3:y/wham &&
                git rev-parse >expect \
                         O:z/a  O:z/b  O:x/c     O:x/d &&
-               test_cmp expect actual
+               test_cmp expect actual &&
+
+               # Test that the two-way merge in y/wham~merged is as expected
+               git cat-file -p :2:y/wham >expect &&
+               git cat-file -p :3:y/wham >other &&
+               >empty &&
+               test_must_fail git merge-file \
+                       -L "HEAD" \
+                       -L "" \
+                       -L "B^0" \
+                       expect empty other &&
+               test_cmp expect y/wham~merged
        )
 '
 
@@ -3776,7 +3880,7 @@ test_expect_success '11f-check: Avoid deleting not-uptodate with dir rename/rena
 #   Commit B: node1/{leaf1,leaf2,leaf5}, node2/{leaf3,leaf4,leaf6}
 #   Expected: node1/{leaf1,leaf2,leaf5,node2/{leaf3,leaf4,leaf6}}
 
-test_expect_success '12a-setup: Moving one directory hierarchy into another' '
+test_setup_12a () {
        test_create_repo 12a &&
        (
                cd 12a &&
@@ -3806,15 +3910,16 @@ test_expect_success '12a-setup: Moving one directory hierarchy into another' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '12a-check: Moving one directory hierarchy into another' '
+test_expect_success '12a: Moving one directory hierarchy into another' '
+       test_setup_12a &&
        (
                cd 12a &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 6 out &&
@@ -3854,7 +3959,7 @@ test_expect_success '12a-check: Moving one directory hierarchy into another' '
 #         To which, I can do no more than shrug my shoulders and say that
 #         even simple rules give weird results when given weird inputs.
 
-test_expect_success '12b-setup: Moving one directory hierarchy into another' '
+test_setup_12b () {
        test_create_repo 12b &&
        (
                cd 12b &&
@@ -3882,15 +3987,16 @@ test_expect_success '12b-setup: Moving one directory hierarchy into another' '
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '12b-check: Moving one directory hierarchy into another' '
+test_expect_success '12b: Moving two directory hierarchies into each other' '
+       test_setup_12b &&
        (
                cd 12b &&
 
                git checkout A^0 &&
 
-               git merge -s recursive B^0 &&
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -s >out &&
                test_line_count = 4 out &&
@@ -3920,7 +4026,7 @@ test_expect_success '12b-check: Moving one directory hierarchy into another' '
 #   NOTE: This is *exactly* like 12c, except that every path is modified on
 #         each side of the merge.
 
-test_expect_success '12c-setup: Moving one directory hierarchy into another w/ content merge' '
+test_setup_12c () {
        test_create_repo 12c &&
        (
                cd 12c &&
@@ -3952,15 +4058,16 @@ test_expect_success '12c-setup: Moving one directory hierarchy into another w/ c
                test_tick &&
                git commit -m "B"
        )
-'
+}
 
-test_expect_success '12c-check: Moving one directory hierarchy into another w/ content merge' '
+test_expect_success '12c: Moving one directory hierarchy into another w/ content merge' '
+       test_setup_12c &&
        (
                cd 12c &&
 
                git checkout A^0 &&
 
-               test_must_fail git merge -s recursive B^0 &&
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 &&
 
                git ls-files -u >out &&
                test_line_count = 12 out &&
@@ -3995,4 +4102,592 @@ test_expect_success '12c-check: Moving one directory hierarchy into another w/ c
        )
 '
 
+# Testcase 12d, Rename/merge of subdirectory into the root
+#   Commit O: a/b/subdir/foo
+#   Commit A: subdir/foo
+#   Commit B: a/b/subdir/foo, a/b/bar
+#   Expected: subdir/foo, bar
+
+test_setup_12d () {
+       test_create_repo 12d &&
+       (
+               cd 12d &&
+
+               mkdir -p a/b/subdir &&
+               test_commit a/b/subdir/foo &&
+
+               git branch O &&
+               git branch A &&
+               git branch B &&
+
+               git checkout A &&
+               mkdir subdir &&
+               git mv a/b/subdir/foo.t subdir/foo.t &&
+               test_tick &&
+               git commit -m "A" &&
+
+               git checkout B &&
+               test_commit a/b/bar
+       )
+}
+
+test_expect_success '12d: Rename/merge subdir into the root, variant 1' '
+       test_setup_12d &&
+       (
+               cd 12d &&
+
+               git checkout A^0 &&
+
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
+
+               git ls-files -s >out &&
+               test_line_count = 2 out &&
+
+               git rev-parse >actual \
+                       HEAD:subdir/foo.t   HEAD:bar.t &&
+               git rev-parse >expect \
+                       O:a/b/subdir/foo.t  B:a/b/bar.t &&
+               test_cmp expect actual &&
+
+               git hash-object bar.t >actual &&
+               git rev-parse B:a/b/bar.t >expect &&
+               test_cmp expect actual &&
+
+               test_must_fail git rev-parse HEAD:a/b/subdir/foo.t &&
+               test_must_fail git rev-parse HEAD:a/b/bar.t &&
+               test_path_is_missing a/ &&
+               test_path_is_file bar.t
+       )
+'
+
+# Testcase 12e, Rename/merge of subdirectory into the root
+#   Commit O: a/b/foo
+#   Commit A: foo
+#   Commit B: a/b/foo, a/b/bar
+#   Expected: foo, bar
+
+test_setup_12e () {
+       test_create_repo 12e &&
+       (
+               cd 12e &&
+
+               mkdir -p a/b &&
+               test_commit a/b/foo &&
+
+               git branch O &&
+               git branch A &&
+               git branch B &&
+
+               git checkout A &&
+               mkdir subdir &&
+               git mv a/b/foo.t foo.t &&
+               test_tick &&
+               git commit -m "A" &&
+
+               git checkout B &&
+               test_commit a/b/bar
+       )
+}
+
+test_expect_success '12e: Rename/merge subdir into the root, variant 2' '
+       test_setup_12e &&
+       (
+               cd 12e &&
+
+               git checkout A^0 &&
+
+               git -c merge.directoryRenames=true merge -s recursive B^0 &&
+
+               git ls-files -s >out &&
+               test_line_count = 2 out &&
+
+               git rev-parse >actual \
+                       HEAD:foo.t   HEAD:bar.t &&
+               git rev-parse >expect \
+                       O:a/b/foo.t  B:a/b/bar.t &&
+               test_cmp expect actual &&
+
+               git hash-object bar.t >actual &&
+               git rev-parse B:a/b/bar.t >expect &&
+               test_cmp expect actual &&
+
+               test_must_fail git rev-parse HEAD:a/b/foo.t &&
+               test_must_fail git rev-parse HEAD:a/b/bar.t &&
+               test_path_is_missing a/ &&
+               test_path_is_file bar.t
+       )
+'
+
+###########################################################################
+# SECTION 13: Checking informational and conflict messages
+#
+# A year after directory rename detection became the default, it was
+# instead decided to report conflicts on the pathname on the basis that
+# some users may expect the new files added or moved into a directory to
+# be unrelated to all the other files in that directory, and thus that
+# directory rename detection is unexpected.  Test that the messages printed
+# match our expectation.
+###########################################################################
+
+# Testcase 13a, Basic directory rename with newly added files
+#   Commit O: z/{b,c}
+#   Commit A: y/{b,c}
+#   Commit B: z/{b,c,d,e/f}
+#   Expected: y/{b,c,d,e/f}, with notices/conflicts for both y/d and y/e/f
+
+test_setup_13a () {
+       test_create_repo 13a_$1 &&
+       (
+               cd 13a_$1 &&
+
+               mkdir z &&
+               echo b >z/b &&
+               echo c >z/c &&
+               git add z &&
+               test_tick &&
+               git commit -m "O" &&
+
+               git branch O &&
+               git branch A &&
+               git branch B &&
+
+               git checkout A &&
+               git mv z y &&
+               test_tick &&
+               git commit -m "A" &&
+
+               git checkout B &&
+               echo d >z/d &&
+               mkdir z/e &&
+               echo f >z/e/f &&
+               git add z/d z/e/f &&
+               test_tick &&
+               git commit -m "B"
+       )
+}
+
+test_expect_success '13a(conflict): messages for newly added files' '
+       test_setup_13a conflict &&
+       (
+               cd 13a_conflict &&
+
+               git checkout A^0 &&
+
+               test_must_fail git merge -s recursive B^0 >out 2>err &&
+
+               test_i18ngrep CONFLICT..file.location.*z/e/f.added.in.B^0.*y/e/f out &&
+               test_i18ngrep CONFLICT..file.location.*z/d.added.in.B^0.*y/d out &&
+
+               git ls-files >paths &&
+               ! grep z/ paths &&
+               grep "y/[de]" paths &&
+
+               test_path_is_missing z/d &&
+               test_path_is_file    y/d &&
+               test_path_is_missing z/e/f &&
+               test_path_is_file    y/e/f
+       )
+'
+
+test_expect_success '13a(info): messages for newly added files' '
+       test_setup_13a info &&
+       (
+               cd 13a_info &&
+
+               git reset --hard &&
+               git checkout A^0 &&
+
+               git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
+
+               test_i18ngrep Path.updated:.*z/e/f.added.in.B^0.*y/e/f out &&
+               test_i18ngrep Path.updated:.*z/d.added.in.B^0.*y/d out &&
+
+               git ls-files >paths &&
+               ! grep z/ paths &&
+               grep "y/[de]" paths &&
+
+               test_path_is_missing z/d &&
+               test_path_is_file    y/d &&
+               test_path_is_missing z/e/f &&
+               test_path_is_file    y/e/f
+       )
+'
+
+# Testcase 13b, Transitive rename with conflicted content merge and default
+#               "conflict" setting
+#   (Related to testcase 1c, 9b)
+#   Commit O: z/{b,c},   x/d_1
+#   Commit A: y/{b,c},   x/d_2
+#   Commit B: z/{b,c,d_3}
+#   Expected: y/{b,c,d_merged}, with two conflict messages for y/d,
+#             one about content, and one about file location
+
+test_setup_13b () {
+       test_create_repo 13b_$1 &&
+       (
+               cd 13b_$1 &&
+
+               mkdir x &&
+               mkdir z &&
+               test_seq 1 10 >x/d &&
+               echo b >z/b &&
+               echo c >z/c &&
+               git add x z &&
+               test_tick &&
+               git commit -m "O" &&
+
+               git branch O &&
+               git branch A &&
+               git branch B &&
+
+               git checkout A &&
+               git mv z y &&
+               echo 11 >>x/d &&
+               git add x/d &&
+               test_tick &&
+               git commit -m "A" &&
+
+               git checkout B &&
+               echo eleven >>x/d &&
+               git mv x/d z/d &&
+               git add z/d &&
+               test_tick &&
+               git commit -m "B"
+       )
+}
+
+test_expect_success '13b(conflict): messages for transitive rename with conflicted content' '
+       test_setup_13b conflict &&
+       (
+               cd 13b_conflict &&
+
+               git checkout A^0 &&
+
+               test_must_fail git merge -s recursive B^0 >out 2>err &&
+
+               test_i18ngrep CONFLICT.*content.*Merge.conflict.in.y/d out &&
+               test_i18ngrep CONFLICT..file.location.*x/d.renamed.to.z/d.*moved.to.y/d out &&
+
+               git ls-files >paths &&
+               ! grep z/ paths &&
+               grep "y/d" paths &&
+
+               test_path_is_missing z/d &&
+               test_path_is_file    y/d
+       )
+'
+
+test_expect_success '13b(info): messages for transitive rename with conflicted content' '
+       test_setup_13b info &&
+       (
+               cd 13b_info &&
+
+               git reset --hard &&
+               git checkout A^0 &&
+
+               test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
+
+               test_i18ngrep CONFLICT.*content.*Merge.conflict.in.y/d out &&
+               test_i18ngrep Path.updated:.*x/d.renamed.to.z/d.in.B^0.*moving.it.to.y/d out &&
+
+               git ls-files >paths &&
+               ! grep z/ paths &&
+               grep "y/d" paths &&
+
+               test_path_is_missing z/d &&
+               test_path_is_file    y/d
+       )
+'
+
+# Testcase 13c, Rename/rename(1to1) due to directory rename
+#   Commit O: z/{b,c},   x/{d,e}
+#   Commit A: y/{b,c,d}, x/e
+#   Commit B: z/{b,c,d}, x/e
+#   Expected: y/{b,c,d}, with info or conflict messages for d (
+#             A: renamed x/d -> z/d; B: renamed z/ -> y/ AND renamed x/d to y/d
+#             One could argue A had partial knowledge of what was done with
+#             d and B had full knowledge, but that's a slippery slope as
+#             shown in testcase 13d.
+
+test_setup_13c () {
+       test_create_repo 13c_$1 &&
+       (
+               cd 13c_$1 &&
+
+               mkdir x &&
+               mkdir z &&
+               test_seq 1 10 >x/d &&
+               echo e >x/e &&
+               echo b >z/b &&
+               echo c >z/c &&
+               git add x z &&
+               test_tick &&
+               git commit -m "O" &&
+
+               git branch O &&
+               git branch A &&
+               git branch B &&
+
+               git checkout A &&
+               git mv z y &&
+               git mv x/d y/ &&
+               test_tick &&
+               git commit -m "A" &&
+
+               git checkout B &&
+               git mv x/d z/d &&
+               git add z/d &&
+               test_tick &&
+               git commit -m "B"
+       )
+}
+
+test_expect_success '13c(conflict): messages for rename/rename(1to1) via transitive rename' '
+       test_setup_13c conflict &&
+       (
+               cd 13c_conflict &&
+
+               git checkout A^0 &&
+
+               test_must_fail git merge -s recursive B^0 >out 2>err &&
+
+               test_i18ngrep CONFLICT..file.location.*x/d.renamed.to.z/d.*moved.to.y/d out &&
+
+               git ls-files >paths &&
+               ! grep z/ paths &&
+               grep "y/d" paths &&
+
+               test_path_is_missing z/d &&
+               test_path_is_file    y/d
+       )
+'
+
+test_expect_success '13c(info): messages for rename/rename(1to1) via transitive rename' '
+       test_setup_13c info &&
+       (
+               cd 13c_info &&
+
+               git reset --hard &&
+               git checkout A^0 &&
+
+               git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
+
+               test_i18ngrep Path.updated:.*x/d.renamed.to.z/d.in.B^0.*moving.it.to.y/d out &&
+
+               git ls-files >paths &&
+               ! grep z/ paths &&
+               grep "y/d" paths &&
+
+               test_path_is_missing z/d &&
+               test_path_is_file    y/d
+       )
+'
+
+# Testcase 13d, Rename/rename(1to1) due to directory rename on both sides
+#   Commit O: a/{z,y}, b/x,     c/w
+#   Commit A: a/z,     b/{y,x}, d/w
+#   Commit B: a/z,     d/x,     c/{y,w}
+#   Expected: a/z, d/{y,x,w} with no file location conflict for x
+#             Easy cases:
+#               * z is always in a; so it stays in a.
+#               * x starts in b, only modified on one side to move into d/
+#               * w starts in c, only modified on one side to move into d/
+#             Hard case:
+#               * A renames a/y to b/y, and B renames b/->d/ => a/y -> d/y
+#               * B renames a/y to c/y, and A renames c/->d/ => a/y -> d/y
+#               No conflict in where a/y ends up, so put it in d/y.
+
+test_setup_13d () {
+       test_create_repo 13d_$1 &&
+       (
+               cd 13d_$1 &&
+
+               mkdir a &&
+               mkdir b &&
+               mkdir c &&
+               echo z >a/z &&
+               echo y >a/y &&
+               echo x >b/x &&
+               echo w >c/w &&
+               git add a b c &&
+               test_tick &&
+               git commit -m "O" &&
+
+               git branch O &&
+               git branch A &&
+               git branch B &&
+
+               git checkout A &&
+               git mv a/y b/ &&
+               git mv c/ d/ &&
+               test_tick &&
+               git commit -m "A" &&
+
+               git checkout B &&
+               git mv a/y c/ &&
+               git mv b/ d/ &&
+               test_tick &&
+               git commit -m "B"
+       )
+}
+
+test_expect_success '13d(conflict): messages for rename/rename(1to1) via dual transitive rename' '
+       test_setup_13d conflict &&
+       (
+               cd 13d_conflict &&
+
+               git checkout A^0 &&
+
+               test_must_fail git merge -s recursive B^0 >out 2>err &&
+
+               test_i18ngrep CONFLICT..file.location.*a/y.renamed.to.b/y.*moved.to.d/y out &&
+               test_i18ngrep CONFLICT..file.location.*a/y.renamed.to.c/y.*moved.to.d/y out &&
+
+               git ls-files >paths &&
+               ! grep b/ paths &&
+               ! grep c/ paths &&
+               grep "d/y" paths &&
+
+               test_path_is_missing b/y &&
+               test_path_is_missing c/y &&
+               test_path_is_file    d/y
+       )
+'
+
+test_expect_success '13d(info): messages for rename/rename(1to1) via dual transitive rename' '
+       test_setup_13d info &&
+       (
+               cd 13d_info &&
+
+               git reset --hard &&
+               git checkout A^0 &&
+
+               git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
+
+               test_i18ngrep Path.updated.*a/y.renamed.to.b/y.*moving.it.to.d/y out &&
+               test_i18ngrep Path.updated.*a/y.renamed.to.c/y.*moving.it.to.d/y out &&
+
+               git ls-files >paths &&
+               ! grep b/ paths &&
+               ! grep c/ paths &&
+               grep "d/y" paths &&
+
+               test_path_is_missing b/y &&
+               test_path_is_missing c/y &&
+               test_path_is_file    d/y
+       )
+'
+
+# Testcase 13e, directory rename in virtual merge base
+#
+# This testcase has a slightly different setup than all the above cases, in
+# order to include a recursive case:
+#
+#      A   C
+#      o - o
+#     / \ / \
+#  O o   X   ?
+#     \ / \ /
+#      o   o
+#      B   D
+#
+#   Commit O: a/{z,y}
+#   Commit A: b/{z,y}
+#   Commit B: a/{z,y,x}
+#   Commit C: b/{z,y,x}
+#   Commit D: b/{z,y}, a/x
+#   Expected: b/{z,y,x}  (sort of; see below for why this might not be expected)
+#
+#   NOTES: 'X' represents a virtual merge base.  With the default of
+#          directory rename detection yielding conflicts, merging A and B
+#          results in a conflict complaining about whether 'x' should be
+#          under 'a/' or 'b/'.  However, when creating the virtual merge
+#          base 'X', since virtual merge bases need to be written out as a
+#          tree, we cannot have a conflict, so some resolution has to be
+#          picked.
+#
+#          In choosing the right resolution, it's worth noting here that
+#          commits C & D are merges of A & B that choose different
+#          locations for 'x' (i.e. they resolve the conflict differently),
+#          and so it would be nice when merging C & D if git could detect
+#          this difference of opinion and report a conflict.  But the only
+#          way to do so that I can think of would be to have the virtual
+#          merge base place 'x' in some directory other than either 'a/' or
+#          'b/', which seems a little weird -- especially since it'd result
+#          in a rename/rename(1to2) conflict with a source path that never
+#          existed in any version.
+#
+#          So, for now, when directory rename detection is set to
+#          'conflict' just avoid doing directory rename detection at all in
+#          the recursive case.  This will not allow us to detect a conflict
+#          in the outer merge for this special kind of setup, but it at
+#          least avoids hitting a BUG().
+#
+test_setup_13e () {
+       test_create_repo 13e &&
+       (
+               cd 13e &&
+
+               mkdir a &&
+               echo z >a/z &&
+               echo y >a/y &&
+               git add a &&
+               test_tick &&
+               git commit -m "O" &&
+
+               git branch O &&
+               git branch A &&
+               git branch B &&
+
+               git checkout A &&
+               git mv a/ b/ &&
+               test_tick &&
+               git commit -m "A" &&
+
+               git checkout B &&
+               echo x >a/x &&
+               git add a &&
+               test_tick &&
+               git commit -m "B" &&
+
+               git branch C A &&
+               git branch D B &&
+
+               git checkout C &&
+               test_must_fail git -c merge.directoryRenames=conflict merge B &&
+               git add b/x &&
+               test_tick &&
+               git commit -m "C" &&
+
+
+               git checkout D &&
+               test_must_fail git -c merge.directoryRenames=conflict merge A &&
+               git add b/x &&
+               mkdir a &&
+               git mv b/x a/x &&
+               test_tick &&
+               git commit -m "D"
+       )
+}
+
+test_expect_success '13e: directory rename detection in recursive case' '
+       test_setup_13e &&
+       (
+               cd 13e &&
+
+               git checkout --quiet D^0 &&
+
+               git -c merge.directoryRenames=conflict merge -s recursive C^0 >out 2>err &&
+
+               test_i18ngrep ! CONFLICT out &&
+               test_i18ngrep ! BUG: err &&
+               test_i18ngrep ! core.dumped err &&
+               test_must_be_empty err &&
+
+               git ls-files >paths &&
+               ! grep a/x paths &&
+               grep b/x paths
+       )
+'
+
 test_done