From: Nick Golden Date: Wed, 1 Apr 2026 19:00:33 +0000 (-0400) Subject: read-cache: disable renames in add_files_to_cache X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c0ce43376b178d876bce2073b81737ce49657def;p=thirdparty%2Fgit.git read-cache: disable renames in add_files_to_cache add_files_to_cache() refreshes the index from worktree changes and does not need rename detection. When unmerged entries and a deleted stage-0 path are present together, rename detection can pair them and rewrite an unmerged diff pair to point at the deleted path. That later makes "git commit -a" and "git add -u" try to stat the deleted path and die with "unable to stat". Disable rename detection in this callback-driven staging path and add a regression test covering the crash. Signed-off-by: Nick Golden Signed-off-by: Junio C Hamano --- diff --git a/read-cache.c b/read-cache.c index 0c07c3aef7..bacb841a2e 100644 --- a/read-cache.c +++ b/read-cache.c @@ -3975,6 +3975,7 @@ int add_files_to_cache(struct repository *repo, const char *prefix, rev.diffopt.format_callback = update_callback; rev.diffopt.format_callback_data = &data; rev.diffopt.flags.override_submodule_config = 1; + rev.diffopt.detect_rename = 0; /* staging worktree changes does not need renames */ rev.max_count = 0; /* do not compare unmerged paths with stage #2 */ /* diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh index 06e83d3333..0a96655cfe 100755 --- a/t/t2200-add-update.sh +++ b/t/t2200-add-update.sh @@ -200,6 +200,44 @@ test_expect_success 'add -u resolves unmerged paths' ' test_cmp expect actual ' +test_expect_success 'add -u avoids rename pairing on unmerged paths' ' + test_create_repo rename-crash && + ( + cd rename-crash && + test_seq 1 100 | + sed "s/.*/line &: same text/" >conflict.txt && + cp conflict.txt bystander.txt && + git add conflict.txt bystander.txt && + git commit -m "initial: two files with identical content" && + main_branch=$(git symbolic-ref --short HEAD) && + git checkout -b feature && + sed "s/^line 50:.*/line 50: FEATURE/" \ + conflict.txt >conflict.txt.tmp && + mv conflict.txt.tmp conflict.txt && + git add conflict.txt && + git commit -m "feature: modify line 50" && + git checkout "$main_branch" && + sed "s/^line 50:.*/line 50: MAIN/" \ + conflict.txt >conflict.txt.tmp && + mv conflict.txt.tmp conflict.txt && + git add conflict.txt && + git commit -m "main: modify line 50 differently" && + test_must_fail git merge feature && + rm bystander.txt && + git add -u >out && + test_must_be_empty out && + git ls-files -u >actual && + test_must_be_empty actual && + git ls-files bystander.txt conflict.txt >actual && + cat >expect <<-\EOF && + conflict.txt + EOF + test_cmp expect actual && + git diff-files --name-only >actual && + test_must_be_empty actual + ) +' + test_expect_success '"add -u non-existent" should fail' ' test_must_fail git add -u non-existent && git ls-files >actual &&