Git development
 help / color / mirror / Atom feed
* [BUG] git apply: pure rename followed by edit fails with core.fileMode=false
@ 2026-10-23 13:53 Hannes Brandstätter-Müller
  2026-11-06 18:11 ` Aniket Gupta
  0 siblings, 1 reply; 6+ messages in thread
From: Hannes Brandstätter-Müller @ 2026-10-23 13:53 UTC (permalink / raw)
  To: git

[-- Attachment #1: Type: text/plain, Size: 2476 bytes --]

Hi Git developers,

I would like to report a possible regression in git apply and ask
for your help with a fix.

With core.fileMode=false, applying a patch series containing a pure
rename followed by an edit to the renamed file fails with:

    error: renamed: wrong type

I encountered this while checking a series generated by
git format-patch. Here is a small reproduction, to run in a temporary
directory with a Git author identity configured:

    git init -q repro && cd repro
    git config core.fileMode false
    printf 'a\nb\nc\n' >file
    git add file && git commit -q -m base
    git mv file renamed && git commit -q -m rename
    sed s/b/B/ renamed >tmp && mv tmp renamed
    git commit -q -a -m edit
    git format-patch --stdout HEAD~2 >series.patch
    git checkout -q HEAD~2
    git apply --check series.patch

I expected the check to succeed, since the series renames the file
and then edits it. Instead, it reports the error above. Applying the
patches separately succeeds, as does checking the combined series
with core.fileMode=true.

Our testing reproduced the failure with Git for Windows 2.55.0,
source-built v2.45.0, and master at 7e34d8174
(2.56.0.236.g7e34d8174). Source-built v2.44.0 and Ubuntu's Git 2.34.1
did not show the problem.

The behavior appears related to 0482c32c33 ("apply: ignore working
tree filemode when !core.filemode, 2023-12-26"), although we have not
confirmed that with a bisect.

Our reading of check_preimage() suggests that the pure rename has
no mode information, leaving previous->new_mode as zero. The later
edit then uses that zero mode and fails the file-type comparison.

The attached patch is a tentative fix, with a regression test. It
falls back to patch->old_mode when previous->new_mode is zero.
I am not familiar enough with this code to be confident that this
is the right approach, so I would appreciate a review of both the
diagnosis and the proposed change.

With this change, our tests passed for both a regular file and an
executable file, without a mode warning. The new regression test
failed without the fix and passed with it. The t41* and t42* tests
also completed with 1,524 passed, no failures, and 12 known
breakages.

Could someone please take a look and help get an appropriate fix
upstream? If I have misunderstood the expected behavior or missed
an existing fix, I would appreciate being pointed in the right
direction.

Thank you for your time and for maintaining Git.

Best regards,
Hannes

[-- Attachment #2: git-apply-pure-rename-upstream.patch --]
[-- Type: text/plain, Size: 1680 bytes --]

diff --git a/apply.c b/apply.c
index a0b7119c6..ecd489391 100644
--- a/apply.c
+++ b/apply.c
@@ -3873,6 +3873,13 @@ static int check_preimage(struct apply_state *state,
 		return error(_("path %s has been renamed/deleted"), old_name);
 	if (previous) {
 		st_mode = previous->new_mode;
+		/*
+		 * Without core.fileMode a pure rename may not know its mode
+		 * (see below); take the one this patch expects, as we do for
+		 * a path read from the working tree.
+		 */
+		if (!st_mode)
+			st_mode = patch->old_mode;
 	} else if (!state->cached) {
 		stat_ret = lstat(old_name, st);
 		if (stat_ret && errno != ENOENT)
diff --git a/t/t4129-apply-samemode.sh b/t/t4129-apply-samemode.sh
index 1d6317bd7..45dee717a 100755
--- a/t/t4129-apply-samemode.sh
+++ b/t/t4129-apply-samemode.sh
@@ -412,4 +412,27 @@ test_expect_success POSIXPERM 'patch mode for mode change is canonicalized' '
 	test_grep "^-rwxrwxrwx" worktree
 '

+test_expect_success 'apply a pure rename followed by an edit with core.fileMode=false' '
+	test_when_finished "rm -rf rename-then-edit series.patch" &&
+	git init rename-then-edit &&
+	(
+		cd rename-then-edit &&
+		git config core.fileMode false &&
+		test_write_lines a b c >file &&
+		git add file &&
+		test_tick && git commit -m base &&
+		git mv file renamed &&
+		test_tick && git commit -m rename &&
+		test_write_lines a B c >renamed &&
+		test_tick && git commit -a -m edit &&
+		git format-patch --stdout HEAD~2 >../series.patch &&
+		git checkout HEAD~2 &&
+		git apply --check ../series.patch &&
+		git apply ../series.patch &&
+		test_write_lines a B c >expect &&
+		test_cmp expect renamed &&
+		test_path_is_missing file
+	)
+'
+
 test_done

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-11-07  5:47 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-23 13:53 [BUG] git apply: pure rename followed by edit fails with core.fileMode=false Hannes Brandstätter-Müller
2026-11-06 18:11 ` Aniket Gupta
2026-11-06 20:36   ` Junio C Hamano
2026-11-07  4:07     ` Aniket Gupta
2026-11-07  5:25       ` Junio C Hamano
2026-11-07  5:47         ` Aniket Gupta

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox