diff --git a/merge-recursive.c b/merge-recursive.c index 4ceb6aac88..3124144011 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -1081,6 +1081,8 @@ static void conflict_rename_rename_2to1(struct merge_options *o, struct diff_filespec *c1 = ci->pair1->two; struct diff_filespec *c2 = ci->pair2->two; char *path = c1->path; /* == c2->path */ + struct merge_file_info mfi_c1; + struct merge_file_info mfi_c2; output(o, 1, "CONFLICT (rename/rename): " "Rename %s->%s in %s. " @@ -1091,22 +1093,32 @@ static void conflict_rename_rename_2to1(struct merge_options *o, remove_file(o, 1, a->path, would_lose_untracked(a->path)); remove_file(o, 1, b->path, would_lose_untracked(b->path)); + mfi_c1 = merge_file_special_markers(o, a, c1, &ci->ren1_other, + o->branch1, c1->path, + o->branch2, ci->ren1_other.path); + mfi_c2 = merge_file_special_markers(o, b, &ci->ren2_other, c2, + o->branch1, ci->ren2_other.path, + o->branch2, c2->path); + if (o->call_depth) { - struct merge_file_info mfi; - mfi = merge_file(o, path, null_sha1, 0, - c1->sha1, c1->mode, - c2->sha1, c2->mode, - ci->branch1, ci->branch2); - output(o, 1, "Adding merged %s", path); - update_file(o, 0, mfi.sha, mfi.mode, path); + /* + * If mfi_c1.clean && mfi_c2.clean, then it might make + * sense to do a two-way merge of those results. But, I + * think in all cases, it makes sense to have the virtual + * merge base just undo the renames; they can be detected + * again later for the non-recursive merge. + */ + remove_file(o, 0, path, 0); + update_file(o, 0, mfi_c1.sha, mfi_c1.mode, a->path); + update_file(o, 0, mfi_c2.sha, mfi_c2.mode, b->path); } else { char *new_path1 = unique_path(o, path, ci->branch1); char *new_path2 = unique_path(o, path, ci->branch2); output(o, 1, "Renaming %s to %s and %s to %s instead", a->path, new_path1, b->path, new_path2); remove_file(o, 0, path, 0); - update_file(o, 0, c1->sha1, c1->mode, new_path1); - update_file(o, 0, c2->sha1, c2->mode, new_path2); + update_file(o, 0, mfi_c1.sha, mfi_c1.mode, new_path1); + update_file(o, 0, mfi_c2.sha, mfi_c2.mode, new_path2); free(new_path2); free(new_path1); } diff --git a/t/t6036-recursive-corner-cases.sh b/t/t6036-recursive-corner-cases.sh index 5a7af0ce91..d8c6bdacc3 100755 --- a/t/t6036-recursive-corner-cases.sh +++ b/t/t6036-recursive-corner-cases.sh @@ -57,23 +57,15 @@ test_expect_success 'merge simple rename+criss-cross with no modifications' ' test_must_fail git merge -s recursive R2^0 && - test 5 = $(git ls-files -s | wc -l) && - test 3 = $(git ls-files -u | wc -l) && - test 0 = $(git ls-files -o | wc -l) && + test 2 = $(git ls-files -s | wc -l) && + test 2 = $(git ls-files -u | wc -l) && + test 2 = $(git ls-files -o | wc -l) && - test $(git rev-parse :0:one) = $(git rev-parse L2:one) && - test $(git rev-parse :0:two) = $(git rev-parse R2:two) && test $(git rev-parse :2:three) = $(git rev-parse L2:three) && test $(git rev-parse :3:three) = $(git rev-parse R2:three) && - cp one merged && - >empty && - test_must_fail git merge-file \ - -L "Temporary merge branch 1" \ - -L "" \ - -L "Temporary merge branch 2" \ - merged empty two && - test $(git rev-parse :1:three) = $(git hash-object merged) + test $(git rev-parse L2:three) = $(git hash-object three~HEAD) && + test $(git rev-parse R2:three) = $(git hash-object three~R2^0) ' # @@ -132,25 +124,15 @@ test_expect_success 'merge criss-cross + rename merges with basic modification' test_must_fail git merge -s recursive R2^0 && - test 5 = $(git ls-files -s | wc -l) && - test 3 = $(git ls-files -u | wc -l) && - test 0 = $(git ls-files -o | wc -l) && + test 2 = $(git ls-files -s | wc -l) && + test 2 = $(git ls-files -u | wc -l) && + test 2 = $(git ls-files -o | wc -l) && - test $(git rev-parse :0:one) = $(git rev-parse L2:one) && - test $(git rev-parse :0:two) = $(git rev-parse R2:two) && test $(git rev-parse :2:three) = $(git rev-parse L2:three) && test $(git rev-parse :3:three) = $(git rev-parse R2:three) && - head -n 10 two >merged && - cp one merge-me && - >empty && - test_must_fail git merge-file \ - -L "Temporary merge branch 1" \ - -L "" \ - -L "Temporary merge branch 2" \ - merge-me empty merged && - - test $(git rev-parse :1:three) = $(git hash-object merge-me) + test $(git rev-parse L2:three) = $(git hash-object three~HEAD) && + test $(git rev-parse R2:three) = $(git hash-object three~R2^0) ' # diff --git a/t/t6042-merge-rename-corner-cases.sh b/t/t6042-merge-rename-corner-cases.sh index bfc3179332..3be5059318 100755 --- a/t/t6042-merge-rename-corner-cases.sh +++ b/t/t6042-merge-rename-corner-cases.sh @@ -376,7 +376,7 @@ test_expect_success 'setup rename/rename (2to1) + modify/modify' ' git commit -m C ' -test_expect_failure 'handle rename/rename (2to1) conflict correctly' ' +test_expect_success 'handle rename/rename (2to1) conflict correctly' ' git checkout B^0 && test_must_fail git merge -s recursive C^0 >out &&