aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--merge-ort.c14
-rwxr-xr-xt/t6423-merge-rename-directories.sh69
2 files changed, 80 insertions, 3 deletions
diff --git a/merge-ort.c b/merge-ort.c
index 325b19b182..e7bdcf7b96 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -2879,6 +2879,20 @@ static int process_renames(struct merge_options *opt,
}
/*
+ * Directory renames can result in rename-to-self; the code
+ * below assumes we have A->B with different A & B, and tries
+ * to move all entries to path B. If A & B are the same path,
+ * the logic can get confused, so skip further processing when
+ * A & B are already the same path.
+ *
+ * As a reminder, we can avoid strcmp here because all paths
+ * are interned in opt->priv->paths; see the comment above
+ * "paths" in struct merge_options_internal.
+ */
+ if (oldpath == newpath)
+ continue;
+
+ /*
* If pair->one->path isn't in opt->priv->paths, that means
* that either directory rename detection removed that
* path, or a parent directory of oldpath was resolved and
diff --git a/t/t6423-merge-rename-directories.sh b/t/t6423-merge-rename-directories.sh
index e1251b4e12..49eb10392b 100755
--- a/t/t6423-merge-rename-directories.sh
+++ b/t/t6423-merge-rename-directories.sh
@@ -4731,7 +4731,7 @@ test_setup_12i () {
mkdir -p source/subdir &&
echo foo >source/subdir/foo &&
- echo bar >source/bar &&
+ printf "%d\n" 1 2 3 4 5 6 7 >source/bar &&
echo baz >source/baz &&
git add source &&
git commit -m orig &&
@@ -4778,6 +4778,69 @@ test_expect_success '12i: Directory rename causes rename-to-self' '
)
'
+# Testcase 12i2, Identical to 12i except that source/subdir/bar modified on unrenamed side
+# Commit O: source/{subdir/foo, bar, baz_1}
+# Commit A: source/{foo, bar_2, baz_1}
+# Commit B: source/{subdir/{foo, bar}, baz_2}
+# Expected: source/{foo, bar, baz_2}, with conflicts on
+# source/bar vs. source/subdir/bar
+
+test_setup_12i2 () {
+ git init 12i2 &&
+ (
+ cd 12i2 &&
+
+ mkdir -p source/subdir &&
+ echo foo >source/subdir/foo &&
+ printf "%d\n" 1 2 3 4 5 6 7 >source/bar &&
+ echo baz >source/baz &&
+ git add source &&
+ git commit -m orig &&
+
+ git branch O &&
+ git branch A &&
+ git branch B &&
+
+ git switch A &&
+ git mv source/subdir/foo source/foo &&
+ echo 8 >> source/bar &&
+ git add source/bar &&
+ git commit -m A &&
+
+ git switch B &&
+ git mv source/bar source/subdir/bar &&
+ echo more baz >>source/baz &&
+ git add source/baz &&
+ git commit -m B
+ )
+}
+
+test_expect_success '12i2: Directory rename causes rename-to-self' '
+ test_setup_12i2 &&
+ (
+ cd 12i2 &&
+
+ git checkout A^0 &&
+
+ test_must_fail git -c merge.directoryRenames=conflict merge -s recursive B^0 &&
+
+ test_path_is_missing source/subdir &&
+ test_path_is_file source/bar &&
+ test_path_is_file source/baz &&
+
+ git ls-files >actual &&
+ uniq <actual >tracked &&
+ test_line_count = 3 tracked &&
+
+ git status --porcelain -uno >actual &&
+ cat >expect <<-\EOF &&
+ UU source/bar
+ M source/baz
+ EOF
+ test_cmp expect actual
+ )
+'
+
# Testcase 12j, Directory rename to root causes rename-to-self
# Commit O: {subdir/foo, bar, baz_1}
# Commit A: {foo, bar, baz_1}
@@ -5106,7 +5169,7 @@ test_setup_12n () {
)
}
-test_expect_failure '12n: Directory rename transitively makes rename back to self' '
+test_expect_success '12n: Directory rename transitively makes rename back to self' '
test_setup_12n &&
(
cd 12n &&
@@ -5166,7 +5229,7 @@ test_setup_12n2 () {
)
}
-test_expect_failure '12n2: Directory rename transitively makes rename back to self' '
+test_expect_success '12n2: Directory rename transitively makes rename back to self' '
test_setup_12n2 &&
(
cd 12n2 &&