From 34d607032c0db6a6c68754e7a339c3caf08d6a79 Mon Sep 17 00:00:00 2001 From: Jerry Zhang Date: Fri, 17 Dec 2021 15:29:02 -0800 Subject: git-apply: skip threeway in add / rename cases Certain invocations of "git apply --3way" will attempt threeway and fail due to missing objects, even though git is able to fall back on apply_fragments and apply the patch successfully with a return value of 0. To fix, return early from try_threeway() in the following cases: - When the patch is a rename and no lines have changed. In this case, "git diff" doesn't record the blob info, so 3way is neither possible nor necessary. - When the patch is an addition and there is no add/add conflict, i.e. direct_to_threeway is false. In this case, threeway will fail since the preimage is not in cache, but isn't necessary anyway since there is no conflict. This fixes a few unecessary error messages when applying these kinds of patches with --3way. It also fixes a reported issue where applying a concatenation of several git produced patches will fail when those patches involve a deletion followed by creation of the same file. Add a test for this case too. (test provided by ) Signed-off-by: Jerry Zhang Signed-off-by: Junio C Hamano --- apply.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'apply.c') diff --git a/apply.c b/apply.c index 43a0aebf4e..64b226acd9 100644 --- a/apply.c +++ b/apply.c @@ -3582,7 +3582,9 @@ static int try_threeway(struct apply_state *state, /* No point falling back to 3-way merge in these cases */ if (patch->is_delete || - S_ISGITLINK(patch->old_mode) || S_ISGITLINK(patch->new_mode)) + S_ISGITLINK(patch->old_mode) || S_ISGITLINK(patch->new_mode) || + (patch->is_new && !patch->direct_to_threeway) || + (patch->is_rename && !patch->lines_added && !patch->lines_deleted)) return -1; /* Preimage the patch was prepared for */ -- cgit v1.2.3