From: "Johannes Schindelin via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Johannes Schindelin <johannes.schindelin@gmx.de>,
Johannes Schindelin <johannes.schindelin@gmx.de>
Subject: [PATCH 2/2] maintenance(geometric): do release the `.idx` files before repacking
Date: Tue, 28 Apr 2026 12:52:48 +0000 [thread overview]
Message-ID: <12ebd5c56ff02cdbae87b0af9404bb666133bb04.1777380768.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.2103.git.1777380768.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>
As is done for all the other maintenance tasks, let's release the ODB
also before starting the geometric repacking. That way, the `.idx` files
won't be `mmap()`ed when they are to be deleted (which does not work on
Windows because you cannot delete files on that platform as long as they
are kept open by a process).
This regression was introduced by 9bc151850c1c (builtin/maintenance:
introduce "geometric-repack" task, 2025-10-24), but was only noticed
once geometric repacking was made the default in 452b12c2e0fe (builtin/
maintenance: use "geometric" strategy by default, 2026-02-24).
The fix recapitulates my work from df76ee7b77f0 (run-command: offer to
close the object store before running, 2021-09-09) & friends.
To guard against future regressions of this kind, add a check to
`run_and_verify_geometric_pack()` in `t7900` that detects orphaned
`.idx` files left behind after repacking. Contrary to interactive
calls, the `git maintenance` call in that test case would _not_ block on
Windows, asking whether to retry deleting that file, which is the reason
why this bug was not caught earlier.
Furthermore, since the default behavior of `DeleteFileW()` was changed
at some point between Windows 10 Build 17134.1304 and Build 18363.657
to use POSIX semantics (see https://stackoverflow.com/a/60512798),
the added orphaned-`.idx` check would be insufficient to catch this
regression on modern Windows without emulating legacy delete semantics
via `GIT_TEST_LEGACY_DELETE=1`.
This fixes https://github.com/git-for-windows/git/issues/6210.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
builtin/gc.c | 1 +
t/t7900-maintenance.sh | 22 +++++++++++++++++++++-
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/builtin/gc.c b/builtin/gc.c
index 3a71e314c9..84a66d3240 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -1590,6 +1590,7 @@ static int maintenance_task_geometric_repack(struct maintenance_run_opts *opts,
pack_geometry_split(&geometry);
child.git_cmd = 1;
+ child.odb_to_close = the_repository->objects;
strvec_pushl(&child.args, "repack", "-d", "-l", NULL);
if (geometry.split < geometry.pack_nr)
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index 4700beacc1..f497f51b23 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -532,7 +532,16 @@ run_and_verify_geometric_pack () {
# And verify that there are no loose objects anymore.
git count-objects -v >count &&
- test_grep '^count: 0$' count
+ test_grep '^count: 0$' count &&
+
+ # Verify that no orphaned .idx files were left behind. On
+ # Windows, a missing odb_to_close causes the parent to hold
+ # mmap handles on .idx files, silently preventing their
+ # deletion by the child git-repack process.
+ ls .git/objects/pack/pack-*.idx .git/objects/pack/pack-*.pack |
+ sed "s/\.pack$/.idx/" |
+ sort | uniq -u >orphaned-idx &&
+ test_must_be_empty orphaned-idx
}
test_expect_success 'geometric repacking task' '
@@ -580,8 +589,19 @@ test_expect_success 'geometric repacking task' '
# And these two small packs should now be merged via the
# geometric repack. The large packfile should remain intact.
+ cp -R .git/objects .git/objects.save &&
run_and_verify_geometric_pack 2 &&
+ # On Windows, verify the same with legacy delete semantics
+ # that reject deletion of mmap-held .idx files.
+ if test_have_prereq MINGW
+ then
+ rm -rf .git/objects &&
+ mv .git/objects.save .git/objects &&
+ test_env GIT_TEST_LEGACY_DELETE=1 \
+ run_and_verify_geometric_pack 2
+ fi &&
+
# If we now add two more objects and repack twice we should
# then see another all-into-one repack. This time around
# though, as we have unreachable objects, we should also see a
--
gitgitgadget
next prev parent reply other threads:[~2026-04-28 12:52 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-28 12:52 [PATCH 0/2] maintenance(geometric): avoid deadlocks on Windows 10 Johannes Schindelin via GitGitGadget
2026-04-28 12:52 ` [PATCH 1/2] mingw: optionally use legacy (non-POSIX) delete semantics Johannes Schindelin via GitGitGadget
2026-05-04 14:12 ` Patrick Steinhardt
2026-05-07 12:49 ` Johannes Schindelin
2026-04-28 12:52 ` Johannes Schindelin via GitGitGadget [this message]
2026-04-28 15:01 ` [PATCH 0/2] maintenance(geometric): avoid deadlocks on Windows 10 Derrick Stolee
2026-05-04 14:12 ` Patrick Steinhardt
2026-05-07 12:51 ` [PATCH v2 " Johannes Schindelin via GitGitGadget
2026-05-07 12:51 ` [PATCH v2 1/2] mingw: optionally use legacy (non-POSIX) delete semantics Johannes Schindelin via GitGitGadget
2026-05-07 12:51 ` [PATCH v2 2/2] maintenance(geometric): do release the `.idx` files before repacking Johannes Schindelin via GitGitGadget
2026-05-08 13:20 ` [PATCH v2 0/2] maintenance(geometric): avoid deadlocks on Windows 10 Patrick Steinhardt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=12ebd5c56ff02cdbae87b0af9404bb666133bb04.1777380768.git.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=git@vger.kernel.org \
--cc=johannes.schindelin@gmx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox