]> git.ipfire.org Git - thirdparty/git.git/commitdiff
read-cache: disable renames in add_files_to_cache
authorNick Golden <blindmansion@gmail.com>
Wed, 1 Apr 2026 19:00:33 +0000 (15:00 -0400)
committerJunio C Hamano <gitster@pobox.com>
Wed, 1 Apr 2026 19:45:06 +0000 (12:45 -0700)
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 <blindmansion@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
read-cache.c
t/t2200-add-update.sh

index 0c07c3aef78ed5ca3587d571e8941c015275580b..bacb841a2e8f1008fbf41cfcb80bb18864b83521 100644 (file)
@@ -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 */
 
        /*
index 06e83d33333dc8e11c48fdf33bd255ea66a41ec8..0a96655cfe734881f6716c4e5737e7cab886b46f 100755 (executable)
@@ -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 &&