Warning, If you are Using Git 2.40 or 2.41 (Q1/Q2 2023), even a git commit -am
can still generate:
no changes added to commit (use "git add" and/or "git commit -a")
This is reported in git-for-windows/git
issue 4462
The crucial part to make it fail was to ensure that no tracked file is left after staging the deletions
mkdir test_repo
cd test_repo
git init
echo test > file1.txt
echo test > file2.txt
git add --all
git commit -m "first commit"
del file1.txt
del file2.txt
git commit -m "remove files" -a
This is fixed with Git 2.42 (Q3 2023).
A few places failed to differentiate the case where the index is truly empty (nothing added) and we haven't yet read from the on-disk index file, which have been corrected with Git 2.42 (Q3 2023).
See commit 2ee045e, commit 7667f4f, commit 866b43e (29 Jun 2023) by Johannes Schindelin (dscho
).
(Merged by Junio C Hamano -- gitster
-- in commit 7f5ad0c, 08 Jul 2023)
commit -a -m
: allow the top-level tree to become empty again
Signed-off-by: Johannes Schindelin
In 03267e8 ("commit
: discard partial cache before (re-)reading it", 2022-11-08, Git v2.40.0-rc0 -- merge listed in batch #1), a memory leak was plugged by discarding any partial index before re-reading it.
The problem with this memory leak fix is that it was based on an incomplete understanding of the logic introduced in 7168624 ("Do not generate full commit log message if it is not going to be used", 2007-11-28, Git v1.5.4-rc0 -- merge).
That logic was introduced to add a shortcut when committing without editing the commit message interactively.
A part of that logic was to ensure that the index was read into memory:
if (!active_nr && read_cache() < 0)
die(...)
Translation to English: If the index has not yet been read, read it, and if that fails, error out.
That logic was incorrect, though: It used !active_nr
as an indicator that the index was not yet read.
Usually this is not a problem because in the vast majority of instances, the index contains at least one entry.
And it was natural to do it this way because at the time that condition was introduced, the index_state
structure had no explicit flag to indicate that it was initialized: This flag was only introduced in 913e0e9 (unpack_trees()
: protect the handcrafted in-core index from read_cache(), 2008-08-23, Git v1.6.1-rc1 -- merge) (unpack_trees()
: protect the handcrafted in-core index from read_cache()
, 2008-08-23), but that commit did not adjust the code path where no index file was found and a new, pristine index was initialized.
Now, when the index does not contain any entry (which is quite common in Git's test suite because it starts quite a many repositories from scratch), subsequent calls to do_read_index()
will mistake the index not to be initialized, and read it again unnecessarily.
This is a problem because after initializing the empty index e.g. the cache_tree
in that index could have been initialized before a subsequent call to do_read_index()
wants to ensure an initialized index.
And if that subsequent call mistakes the index not to have been initialized, it would lead to leaked memory.
The correct fix for that memory leak is to adjust the condition so that it does not mistake active_nr == 0
to mean that the index has not yet been read.
Using the initialized
flag instead, we avoid that mistake, and as a bonus we can fix a bug at the same time that was introduced by the memory leak fix: When deleting all tracked files and then asking git commit -a -m ...
(man) to commit the result, Git would internally update the index, then discard and re-read the index undoing the update, and fail to commit anything.