Skip to content

Commit 95983da

Browse files
newrengitster
authored andcommitted
merge-recursive: fix rename/rename(1to2) for working tree with a binary
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 <[email protected]> Signed-off-by: Elijah Newren <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 172e8ff commit 95983da

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

merge-recursive.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,6 +1750,18 @@ static int handle_rename_rename_1to2(struct merge_options *opt,
17501750
return -1;
17511751
}
17521752

1753+
if (!mfi.clean && mfi.blob.mode == a->mode &&
1754+
oideq(&mfi.blob.oid, &a->oid)) {
1755+
/*
1756+
* Getting here means we were attempting to merge a binary
1757+
* blob. Since we can't merge binaries, the merge algorithm
1758+
* just takes one side. But we don't want to copy the
1759+
* contents of one side to both paths; we'd rather use the
1760+
* original content at the given path for each path.
1761+
*/
1762+
oidcpy(&mfi.blob.oid, &b->oid);
1763+
mfi.blob.mode = b->mode;
1764+
}
17531765
add = &ci->ren2->dst_entry->stages[flip_stage(3)];
17541766
if (is_valid(add)) {
17551767
add->path = mfi.blob.path = b->path;

t/t6042-merge-rename-corner-cases.sh

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,4 +1379,59 @@ test_expect_success 'check nested conflicts from rename/rename(2to1)' '
13791379
)
13801380
'
13811381

1382+
# Testcase rename/rename(1to2) of a binary file
1383+
# Commit O: orig
1384+
# Commit A: orig-A
1385+
# Commit B: orig-B
1386+
# Expected: CONFLICT(rename/rename) message, three unstaged entries in the
1387+
# index, and contents of orig-[AB] at path orig-[AB]
1388+
test_setup_rename_rename_1_to_2_binary () {
1389+
test_create_repo rename_rename_1_to_2_binary &&
1390+
(
1391+
cd rename_rename_1_to_2_binary &&
1392+
1393+
echo '* binary' >.gitattributes &&
1394+
git add .gitattributes &&
1395+
1396+
test_seq 1 10 >orig &&
1397+
git add orig &&
1398+
git commit -m orig &&
1399+
1400+
git branch A &&
1401+
git branch B &&
1402+
1403+
git checkout A &&
1404+
git mv orig orig-A &&
1405+
test_seq 1 11 >orig-A &&
1406+
git add orig-A &&
1407+
git commit -m orig-A &&
1408+
1409+
git checkout B &&
1410+
git mv orig orig-B &&
1411+
test_seq 0 10 >orig-B &&
1412+
git add orig-B &&
1413+
git commit -m orig-B
1414+
1415+
)
1416+
}
1417+
1418+
test_expect_success 'rename/rename(1to2) with a binary file' '
1419+
test_setup_rename_rename_1_to_2_binary &&
1420+
(
1421+
cd rename_rename_1_to_2_binary &&
1422+
1423+
git checkout A^0 &&
1424+
1425+
test_must_fail git merge -s recursive B^0 &&
1426+
1427+
# Make sure the index has the right number of entries
1428+
git ls-files -s >actual &&
1429+
test_line_count = 4 actual &&
1430+
1431+
git rev-parse A:orig-A B:orig-B >expect &&
1432+
git hash-object orig-A orig-B >actual &&
1433+
test_cmp expect actual
1434+
)
1435+
'
1436+
13821437
test_done

0 commit comments

Comments
 (0)