@matheusbsbs / matheus-bagliano / commits / 95983da6b4
Fork 0

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 <zhangchunlin@gmail.com> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Elijah Newren committed May 13, 2020 at 23:56 UTC 95983da6b461a4394117d4f9fcca211d7fc1403f
2 files changed +67
merge-recursive.c
+12
@@ -1750,6 +1750,18 @@ static int handle_rename_rename_1to2(struct merge_options *opt,
1750 return -1;
1751 }
1752
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 + }
1765 add = &ci->ren2->dst_entry->stages[flip_stage(3)];
1766 if (is_valid(add)) {
1767 add->path = mfi.blob.path = b->path;
t/t6042-merge-rename-corner-cases.sh
+55
@@ -1379,4 +1379,59 @@ test_expect_success 'check nested conflicts from rename/rename(2to1)' '
1379 )
1380 '
1381
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 +
1437 test_done