From: "Elijah Newren via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Elijah Newren <newren@gmail.com>, Elijah Newren <newren@gmail.com>
Subject: [PATCH] merge-recursive: fix rename/rename(1to2) for working tree with a binary
Date: Wed, 13 May 2020 23:56:32 +0000 [thread overview]
Message-ID: <pull.784.git.git.1589414193064.gitgitgadget@gmail.com> (raw)
From: Elijah Newren <newren@gmail.com>
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>
---
merge-recursive: fix rename/rename(1to2) for working tree with a binary
rename/rename(1to2) is unique among our conflict resolutions in that it
tries to put the as-merged-as-possible contents into two different
paths, so I think this should be the only code path that needs an update
for this issue.
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-784%2Fnewren%2Frr1to2-binary-v1
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-784/newren/rr1to2-binary-v1
Pull-Request: https://github.com/git/git/pull/784
merge-recursive.c | 12 ++++++
t/t6042-merge-rename-corner-cases.sh | 55 ++++++++++++++++++++++++++++
2 files changed, 67 insertions(+)
diff --git a/merge-recursive.c b/merge-recursive.c
index d92e2acf1ed..36948eafb75 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -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;
diff --git a/t/t6042-merge-rename-corner-cases.sh b/t/t6042-merge-rename-corner-cases.sh
index b047cf1c1c3..f163893ff97 100755
--- a/t/t6042-merge-rename-corner-cases.sh
+++ b/t/t6042-merge-rename-corner-cases.sh
@@ -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
base-commit: b994622632154fc3b17fb40a38819ad954a5fb88
--
gitgitgadget
reply other threads:[~2020-05-13 23:56 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.784.git.git.1589414193064.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=newren@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.