sequencer: release the ODB before spawning git commit

As of 4557f1add2 (rebase--helper: add a builtin helper for interactive
rebases, 2017-02-09), continuing an interactive rebase uses the builtin
sequencer, which spawns `git commit`.

The child may trigger auto-maintenance, which may need to replace files
for which the sequencer still holds resources. See
https://github.com/git-for-windows/git/issues/6315: on Windows, this
produces unlink retry prompts that cannot succeed while the sequencer
waits for the child.

Resources such as file handles or memory mappings must be released
before spawning a command that may run auto-maintenance, as established
by 28d04e1ec1 (run-command: offer to close the object store before
running, 2021-09-09): release the ODB file handles and memory mappings,
so that auto-gc can repack (potentially deleting existing packfiles in
the process); If the sequencer needs to access the ODB afterwards, it
will gracefully (re-)open the ODB.

Release the sequencer's ODB before spawning `git commit`. The regression
test uses the legacy-delete trick introduced by 69ed0e35a7 (mingw:
optionally use legacy (non-POSIX) delete semantics, 2026-05-07) to
trigger the failure on modern Windows.

Assisted-by: GPT-5.6 Sol
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
main
Johannes Schindelin 2026-08-12 09:54:57 +00:00 committed by Junio C Hamano
parent 11c6700f10
commit 65cda10d5b
2 changed files with 19 additions and 0 deletions

View File

@ -1127,6 +1127,7 @@ static int run_git_commit(const char *defmsg,
struct child_process cmd = CHILD_PROCESS_INIT;

cmd.git_cmd = 1;
cmd.odb_to_close = the_repository->objects;

if (is_rebase_i(opts) &&
((opts->committer_date_is_author_date && !opts->ignore_date) ||

View File

@ -65,6 +65,24 @@ test_expect_success 'setup' '
test_commit P fileP
'

test_expect_success MINGW 'rebase releases object database before committing' '
test_when_finished "rm -f .git/hooks/post-commit repacked packs" &&
git switch -C repack-rewrite primary &&
git repack -ad &&
write_script .git/hooks/post-commit <<-\EOF &&
git repack -ad &&
>repacked
EOF
(
set_fake_editor &&
FAKE_LINES="reword 1" GIT_TEST_LEGACY_DELETE=1 \
git -c core.commitGraph=false rebase -i HEAD^
) &&
test_path_is_file repacked &&
ls .git/objects/pack/*.pack >packs &&
test_line_count = 1 packs
'

# "exec" commands are run with the user shell by default, but this may
# be non-POSIX. For example, if SHELL=zsh then ">file" doesn't work
# to create a file. Unsetting SHELL avoids such non-portable behavior