It is possible to delete a committed file from the index and then add it
as intent-to-add. After `git checkout HEAD` or `git restore --staged`,
the file should be identical in the index and HEAD. This patch provides
the desired behavior even when the file is empty in the index.

Signed-off-by: Varun Naik <[email protected]>
---
CC Jeff because you wrote the code that I am changing now.

checkout.c:update_some() discards the newly created cache entry when its
mode and oid match those of the old entry. Since an ita file has the
same oid as an empty file, an empty deleted ita file passes both of
these checks, and the new entry is discarded. In this case, the file
should be added to the cache instead.

This change should not affect newly added ita files. For those, inside
tree.c:read_tree_1(), tree_entry_interesting() returns
entry_not_interesting, so fn (which points to update_some()) is never
called.

To the best of my understanding, the only other command that makes
changes to the index differently for nonempty vs empty deleted ita files
is "reset", which I am fixing in [0]. I am separating the two changes
because this change affects "restore", which has not reached maint yet.

[0]: https://public-inbox.org/git/[email protected]/

 builtin/checkout.c        |  1 +
 t/t2022-checkout-paths.sh | 11 +++++++++++
 t/t2070-restore.sh        | 11 +++++++++++
 3 files changed, 23 insertions(+)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 91f8509f85..27daa09c3c 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -126,6 +126,7 @@ static int update_some(const struct object_id *oid, struct 
strbuf *base,
        if (pos >= 0) {
                struct cache_entry *old = active_cache[pos];
                if (ce->ce_mode == old->ce_mode &&
+                   !ce_intent_to_add(old) &&
                    oideq(&ce->oid, &old->oid)) {
                        old->ce_flags |= CE_UPDATE;
                        discard_cache_entry(ce);
diff --git a/t/t2022-checkout-paths.sh b/t/t2022-checkout-paths.sh
index fc3eb43b89..74add853fd 100755
--- a/t/t2022-checkout-paths.sh
+++ b/t/t2022-checkout-paths.sh
@@ -78,4 +78,15 @@ test_expect_success 'do not touch files that are already 
up-to-date' '
        test_cmp expect actual
 '
 
+test_expect_success 'checkout HEAD adds deleted intent-to-add file back to 
index' '
+       echo "nonempty" >nonempty &&
+       >empty &&
+       git add nonempty empty &&
+       git commit -m "create files to be deleted" &&
+       git rm --cached nonempty empty &&
+       git add -N nonempty empty &&
+       git checkout HEAD nonempty empty &&
+       git diff --staged --exit-code
+'
+
 test_done
diff --git a/t/t2070-restore.sh b/t/t2070-restore.sh
index 2650df1966..09b1543a5b 100755
--- a/t/t2070-restore.sh
+++ b/t/t2070-restore.sh
@@ -95,4 +95,15 @@ test_expect_success 'restore --ignore-unmerged ignores 
unmerged entries' '
        )
 '
 
+test_expect_success 'restore --staged adds deleted intent-to-add file back to 
index' '
+       echo "nonempty" >nonempty &&
+       >empty &&
+       git add nonempty empty &&
+       git commit -m "create files to be deleted" &&
+       git rm --cached nonempty empty &&
+       git add -N nonempty empty &&
+       git restore --staged nonempty empty &&
+       git diff --staged --exit-code
+'
+
 test_done
-- 
2.22.0

Reply via email to