diff --git a/merge-recursive.c b/merge-recursive.c index 3124144011..500efffb34 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -992,6 +992,46 @@ static struct merge_file_info merge_file(struct merge_options *o, return merge_file_1(o, &one, &a, &b, branch1, branch2); } +static void handle_change_delete(struct merge_options *o, + const char *path, + const unsigned char *o_sha, int o_mode, + const unsigned char *a_sha, int a_mode, + const unsigned char *b_sha, int b_mode, + const char *change, const char *change_past) +{ + 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 (%s/delete): %s deleted in %s " + "and %s in %s. Version %s of %s left in tree%s%s.", + change, path, o->branch1, + change_past, o->branch2, o->branch2, path, + NULL == renamed ? "" : " at ", + NULL == renamed ? "" : renamed); + update_file(o, 0, b_sha, b_mode, renamed ? renamed : path); + } else { + output(o, 1, "CONFLICT (%s/delete): %s deleted in %s " + "and %s in %s. Version %s of %s left in tree%s%s.", + change, path, o->branch2, + change_past, o->branch1, o->branch1, path, + NULL == renamed ? "" : " at ", + NULL == renamed ? "" : renamed); + update_file(o, 0, a_sha, a_mode, renamed ? renamed : path); + } + free(renamed); +} + static void conflict_rename_delete(struct merge_options *o, struct diff_filepair *pair, const char *rename_branch, @@ -1409,44 +1449,18 @@ static int blob_unchanged(const unsigned char *o_sha, return ret; } -static void handle_delete_modify(struct merge_options *o, +static void handle_modify_delete(struct merge_options *o, const char *path, unsigned char *o_sha, int o_mode, unsigned char *a_sha, int a_mode, unsigned char *b_sha, int b_mode) { - 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 == 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 == renamed ? "" : " at ", - NULL == renamed ? "" : renamed); - update_file(o, 0, a_sha, a_mode, renamed ? renamed : path); - } - free(renamed); - + handle_change_delete(o, + path, + o_sha, o_mode, + a_sha, a_mode, + b_sha, b_mode, + "modify", "modified"); } static int merge_content(struct merge_options *o, @@ -1612,7 +1626,7 @@ static int process_entry(struct merge_options *o, } else { /* Modify/delete; deleted side may have put a directory in the way */ clean_merge = 0; - handle_delete_modify(o, path, o_sha, o_mode, + handle_modify_delete(o, path, o_sha, o_mode, a_sha, a_mode, b_sha, b_mode); } } else if ((!o_sha && a_sha && !b_sha) || diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh index d96d3c5975..74dcf20b88 100755 --- a/t/t6022-merge-rename.sh +++ b/t/t6022-merge-rename.sh @@ -303,7 +303,7 @@ test_expect_success 'Rename+D/F conflict; renamed file merges but dir in way' ' git checkout -q renamed-file-has-no-conflicts^0 && test_must_fail git merge --strategy=recursive dir-in-way >output && - grep "CONFLICT (delete/modify): dir/file-in-the-way" output && + grep "CONFLICT (modify/delete): dir/file-in-the-way" output && grep "Auto-merging dir" output && grep "Adding as dir~HEAD instead" output && @@ -325,7 +325,7 @@ test_expect_success 'Same as previous, but merged other way' ' test_must_fail git merge --strategy=recursive renamed-file-has-no-conflicts >output 2>errors && ! grep "error: refusing to lose untracked file at" errors && - grep "CONFLICT (delete/modify): dir/file-in-the-way" output && + grep "CONFLICT (modify/delete): dir/file-in-the-way" output && grep "Auto-merging dir" output && grep "Adding as dir~renamed-file-has-no-conflicts instead" output &&