Skip to content

Commit

Permalink
merge-recursive: fix rename/rename(1to2) for working tree with a binary
Browse files Browse the repository at this point in the history
With a rename/rename(1to2) conflict, we attempt to do a three-way merge
of the file contents, so that the correct contents can be placed in the
working tree at both paths.  If the file is a binary, however, no
content merging is possible and we should just use the original version
of the file at each of the paths.

Reported-by: Chunlin Zhang <zhangchunlin@gmail.com>
Signed-off-by: Elijah Newren <newren@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
newren authored and gitster committed May 14, 2020
1 parent 172e8ff commit 95983da
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 0 deletions.
12 changes: 12 additions & 0 deletions merge-recursive.c
Expand Up @@ -1750,6 +1750,18 @@ static int handle_rename_rename_1to2(struct merge_options *opt,
return -1;
}

if (!mfi.clean && mfi.blob.mode == a->mode &&
oideq(&mfi.blob.oid, &a->oid)) {
/*
* Getting here means we were attempting to merge a binary
* blob. Since we can't merge binaries, the merge algorithm
* just takes one side. But we don't want to copy the
* contents of one side to both paths; we'd rather use the
* original content at the given path for each path.
*/
oidcpy(&mfi.blob.oid, &b->oid);
mfi.blob.mode = b->mode;
}
add = &ci->ren2->dst_entry->stages[flip_stage(3)];
if (is_valid(add)) {
add->path = mfi.blob.path = b->path;
Expand Down
55 changes: 55 additions & 0 deletions t/t6042-merge-rename-corner-cases.sh
Expand Up @@ -1379,4 +1379,59 @@ test_expect_success 'check nested conflicts from rename/rename(2to1)' '
)
'

# Testcase rename/rename(1to2) of a binary file
# Commit O: orig
# Commit A: orig-A
# Commit B: orig-B
# Expected: CONFLICT(rename/rename) message, three unstaged entries in the
# index, and contents of orig-[AB] at path orig-[AB]
test_setup_rename_rename_1_to_2_binary () {
test_create_repo rename_rename_1_to_2_binary &&
(
cd rename_rename_1_to_2_binary &&

echo '* binary' >.gitattributes &&
git add .gitattributes &&

test_seq 1 10 >orig &&
git add orig &&
git commit -m orig &&

git branch A &&
git branch B &&

git checkout A &&
git mv orig orig-A &&
test_seq 1 11 >orig-A &&
git add orig-A &&
git commit -m orig-A &&

git checkout B &&
git mv orig orig-B &&
test_seq 0 10 >orig-B &&
git add orig-B &&
git commit -m orig-B

)
}

test_expect_success 'rename/rename(1to2) with a binary file' '
test_setup_rename_rename_1_to_2_binary &&
(
cd rename_rename_1_to_2_binary &&
git checkout A^0 &&
test_must_fail git merge -s recursive B^0 &&
# Make sure the index has the right number of entries
git ls-files -s >actual &&
test_line_count = 4 actual &&
git rev-parse A:orig-A B:orig-B >expect &&
git hash-object orig-A orig-B >actual &&
test_cmp expect actual
)
'

test_done

0 comments on commit 95983da

Please sign in to comment.