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 <i@zenithal.me>) Signed-off-by: Jerry Zhang <jerry@skydio.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
e9d7761bb9
commit
34d607032c
4
apply.c
4
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 */
|
||||
|
@ -275,4 +275,22 @@ test_expect_success 'apply full-index patch with 3way' '
|
||||
git apply --3way --index bin.diff
|
||||
'
|
||||
|
||||
test_expect_success 'apply delete then new patch with 3way' '
|
||||
git reset --hard main &&
|
||||
test_write_lines 2 > delnew &&
|
||||
git add delnew &&
|
||||
git diff --cached >> new.patch &&
|
||||
git reset --hard &&
|
||||
test_write_lines 1 > delnew &&
|
||||
git add delnew &&
|
||||
git commit -m "delnew" &&
|
||||
rm delnew &&
|
||||
git diff >> delete-then-new.patch &&
|
||||
cat new.patch >> delete-then-new.patch &&
|
||||
|
||||
git checkout -- . &&
|
||||
# Apply must succeed.
|
||||
git apply --3way delete-then-new.patch
|
||||
'
|
||||
|
||||
test_done
|
||||
|
Loading…
Reference in New Issue
Block a user