summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--merge-recursive.c38
-rwxr-xr-xt/t6036-recursive-corner-cases.sh4
2 files changed, 26 insertions, 16 deletions
diff --git a/merge-recursive.c b/merge-recursive.c
index 8b88d6266c..897cada6cf 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -1322,27 +1322,42 @@ error_return:
static void handle_delete_modify(struct merge_options *o,
const char *path,
- const char *new_path,
+ unsigned char *o_sha, int o_mode,
unsigned char *a_sha, int a_mode,
unsigned char *b_sha, int b_mode)
{
- if (!a_sha) {
+ char *renamed = NULL;
+ if (dir_in_way(path, !o->call_depth)) {
+ renamed = unique_path(o, path, a_sha ? o->branch1 : o->branch2);
+ }
+
+ if (o->call_depth) {
+ /*
+ * We cannot arbitrarily accept either a_sha or b_sha as
+ * correct; since there is no true "middle point" between
+ * them, simply reuse the base version for virtual merge base.
+ */
+ remove_file_from_cache(path);
+ update_file(o, 0, o_sha, o_mode, renamed ? renamed : path);
+ } else if (!a_sha) {
output(o, 1, "CONFLICT (delete/modify): %s deleted in %s "
"and modified in %s. Version %s of %s left in tree%s%s.",
path, o->branch1,
o->branch2, o->branch2, path,
- NULL == new_path ? "" : " at ",
- NULL == new_path ? "" : new_path);
- update_file(o, 0, b_sha, b_mode, new_path ? new_path : path);
+ NULL == renamed ? "" : " at ",
+ NULL == renamed ? "" : renamed);
+ update_file(o, 0, b_sha, b_mode, renamed ? renamed : path);
} else {
output(o, 1, "CONFLICT (delete/modify): %s deleted in %s "
"and modified in %s. Version %s of %s left in tree%s%s.",
path, o->branch2,
o->branch1, o->branch1, path,
- NULL == new_path ? "" : " at ",
- NULL == new_path ? "" : new_path);
- update_file(o, 0, a_sha, a_mode, new_path ? new_path : path);
+ NULL == renamed ? "" : " at ",
+ NULL == renamed ? "" : renamed);
+ update_file(o, 0, a_sha, a_mode, renamed ? renamed : path);
}
+ free(renamed);
+
}
static int merge_content(struct merge_options *o,
@@ -1512,14 +1527,9 @@ static int process_entry(struct merge_options *o,
remove_file(o, 1, path, !a_sha);
} else {
/* Modify/delete; deleted side may have put a directory in the way */
- char *renamed = NULL;
clean_merge = 0;
- if (dir_in_way(path, !o->call_depth)) {
- renamed = unique_path(o, path, a_sha ? o->branch1 : o->branch2);
- }
- handle_delete_modify(o, path, renamed,
+ handle_delete_modify(o, path, o_sha, o_mode,
a_sha, a_mode, b_sha, b_mode);
- free(renamed);
}
} else if ((!o_sha && a_sha && !b_sha) ||
(!o_sha && !a_sha && b_sha)) {
diff --git a/t/t6036-recursive-corner-cases.sh b/t/t6036-recursive-corner-cases.sh
index b046e1be71..314fdaeb18 100755
--- a/t/t6036-recursive-corner-cases.sh
+++ b/t/t6036-recursive-corner-cases.sh
@@ -296,7 +296,7 @@ test_expect_success 'setup criss-cross + modify/delete resolved differently' '
git tag E
'
-test_expect_failure 'git detects conflict merging criss-cross+modify/delete' '
+test_expect_success 'git detects conflict merging criss-cross+modify/delete' '
git checkout D^0 &&
test_must_fail git merge -s recursive E^0 &&
@@ -308,7 +308,7 @@ test_expect_failure 'git detects conflict merging criss-cross+modify/delete' '
test $(git rev-parse :2:file) = $(git rev-parse B:file)
'
-test_expect_failure 'git detects conflict merging criss-cross+modify/delete, reverse direction' '
+test_expect_success 'git detects conflict merging criss-cross+modify/delete, reverse direction' '
git reset --hard &&
git checkout E^0 &&