Message ID | 08c50b64e2a93300eed196505936e58ce8bb639b.1688044991.git.gitgitgadget@gmail.com (mailing list archive) |
---|---|
State | Accepted |
Commit | 2ee045eea103e8818ffe0c4085fad3f6b535c8d6 |
Headers | show |
Series | commit -a -m: allow the top-level tree to become empty again | expand |
"Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com> writes: > 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. Well described. It does make sense to turn !active_nr used here into a check on the .initialized member. > 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 > 913e0e99b6a (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. My mistake, but after 15 years it probably is beyond statute of limitations ;-) > 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 ...` 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. That does sound like the primary bug fixed with this change, not a bonus, but anyway, the change is very sensible and clearly described with a good test. Will queue. Thanks.
diff --git a/builtin/commit.c b/builtin/commit.c index 65a5c0e29d5..4cf2baaf943 100644 --- a/builtin/commit.c +++ b/builtin/commit.c @@ -998,11 +998,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix, struct object_id oid; const char *parent = "HEAD"; - if (!the_index.cache_nr) { - discard_index(&the_index); - if (repo_read_index(the_repository) < 0) - die(_("Cannot read index")); - } + if (!the_index.initialized && repo_read_index(the_repository) < 0) + die(_("Cannot read index")); if (amend) parent = "HEAD^1"; diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh index be394f1131a..c01492f33f8 100755 --- a/t/t2200-add-update.sh +++ b/t/t2200-add-update.sh @@ -197,4 +197,15 @@ test_expect_success '"add -u non-existent" should fail' ' ! grep "non-existent" actual ' +test_expect_success '"commit -a" implies "add -u" if index becomes empty' ' + git rm -rf \* && + git commit -m clean-slate && + test_commit file1 && + rm file1.t && + test_tick && + git commit -a -m remove && + git ls-tree HEAD: >out && + test_must_be_empty out +' + test_done