On a rename 2to1 conflict, where both a and b are renamed to c, the other branch may have deleted a or b. This currently luckily works for files but fails for symlinks. Fix conflict_rename_rename_2to1 to not merge_file_special_markers() with diff_filespecs where mode == 0. The alternative would be to make merge_file_1() handle it. Mark the corresponding testcase in t6042 as fixed. Signed-off-by: Nicolas Cavallari <nicolas.cavallari@xxxxxxxxxxxxxxxxxxxxxxx> --- merge-recursive.c | 28 ++++++++++++++++++++++------ t/t6042-merge-rename-corner-cases.sh | 2 +- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/merge-recursive.c b/merge-recursive.c index b7ff1ada3..0e5a3e3ed 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -1305,13 +1305,29 @@ static int conflict_rename_rename_2to1(struct merge_options *o, remove_file(o, 1, a->path, o->call_depth || would_lose_untracked(a->path)); remove_file(o, 1, b->path, o->call_depth || would_lose_untracked(b->path)); - if (merge_file_special_markers(o, a, c1, &ci->ren1_other, - o->branch1, c1->path, - o->branch2, ci->ren1_other.path, &mfi_c1) || - merge_file_special_markers(o, b, &ci->ren2_other, c2, - o->branch1, ci->ren2_other.path, - o->branch2, c2->path, &mfi_c2)) + // The other branch may have deleted a, as indicated by mode == 0. + if (ci->ren1_other.mode == 0) { + mfi_c1.clean = 0; + mfi_c1.merge = 0; + mfi_c1.mode = c1->mode; + oidcpy(&mfi_c1.oid, &c1->oid); + } else if (merge_file_special_markers(o, a, c1, &ci->ren1_other, + o->branch1, c1->path, + o->branch2, ci->ren1_other.path, + &mfi_c1)) { return -1; + } + + if (ci->ren2_other.mode == 0) { + mfi_c2.clean = 0; + mfi_c2.merge = 0; + mfi_c2.mode = c2->mode; + oidcpy(&mfi_c2.oid, &c2->oid); + } else if (merge_file_special_markers(o, b, &ci->ren2_other, c2, + o->branch1, ci->ren2_other.path, + o->branch2, c2->path, &mfi_c2)) { + return -1; + } if (o->call_depth) { /* diff --git a/t/t6042-merge-rename-corner-cases.sh b/t/t6042-merge-rename-corner-cases.sh index ea4e14cbd..34b16d5d7 100755 --- a/t/t6042-merge-rename-corner-cases.sh +++ b/t/t6042-merge-rename-corner-cases.sh @@ -605,7 +605,7 @@ test_expect_success 'setup rename/rename/delete/delete conflict' ' git commit -m C ' -test_expect_failure 'rename/rename/delete/delete leaves at least one file' ' +test_expect_success 'rename/rename/delete/delete leaves at least one file' ' git checkout B^0 && test_must_fail git merge -s recursive C^0 && -- 2.11.0