All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Thomas Bachem via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Phillip Wood <phillip.wood@dunelm.org.uk>,
	Patrick Steinhardt <ps@pks.im>,
	Junio C Hamano <gitster@pobox.com>,
	Johannes Schindelin <johannes.schindelin@gmx.de>,
	Thomas Bachem <mail@thomasbachem.com>,
	Thomas Bachem <mail@thomasbachem.com>
Subject: [PATCH v2 3/3] sequencer: keep auto maintenance out of the commands a sequence spawns
Date: Fri, 04 Sep 2026 15:51:26 +0000	[thread overview]
Message-ID: <9a6fc0427a8bc7e7abcc0518214b1dafc2efaa6a.1788537086.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.2217.v2.git.1788537086.gitgitgadget@gmail.com>

From: Thomas Bachem <mail@thomasbachem.com>

The "git commit" and "git merge" the sequencer spawns, and the git
commands an exec runs, each start "git maintenance run --auto
--detach", which then works in the background against the sequence
itself. A "rerere gc" started by the commit of one "git rebase
--continue" holds MERGE_RR.lock when the next pick needs it, and a
repack deletes packs the sequencer still has open, which 65cda10d5b
(sequencer: release the ODB before spawning git commit, 2026-08-12)
had to work around.

The loose objects a sequence creates wait for the run at its end that
the previous commit added. Whether a sequence can be long enough to
suffer from them before that remains to be seen. Pass
maintenance.auto=false and gc.auto=0 to the spawned commands through
GIT_CONFIG_PARAMETERS, which the shell of an exec command hands on to
whatever it runs, appended after the user's own -c settings so that
ours win, and built once per run. A command the user runs while the
sequence is stopped, like "git commit --amend" at an edit, is not the
sequencer's to control and still runs maintenance.

Assisted-by: Claude Fable 5.1
Signed-off-by: Thomas Bachem <mail@thomasbachem.com>
---
 sequencer.c                     | 39 ++++++++++++++++++++++++++++++---
 t/t3418-rebase-continue.sh      | 18 +++++++++++++++
 t/t3510-cherry-pick-sequence.sh | 17 ++++++++++++++
 3 files changed, 71 insertions(+), 3 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 67e1c38762..5df07750a7 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -234,6 +234,11 @@ struct replay_ctx {
 	 * Whether message contains a commit message.
 	 */
 	unsigned have_message :1;
+	/*
+	 * The GIT_CONFIG_PARAMETERS value that keeps auto maintenance out
+	 * of the commands we spawn, built on first use.
+	 */
+	struct strbuf config_parameters;
 };
 
 struct replay_ctx* replay_ctx_new(void)
@@ -242,6 +247,7 @@ struct replay_ctx* replay_ctx_new(void)
 
 	strbuf_init(&ctx->current_fixups, 0);
 	strbuf_init(&ctx->message, 0);
+	strbuf_init(&ctx->config_parameters, 0);
 
 	return ctx;
 }
@@ -407,6 +413,7 @@ static void replay_ctx_release(struct replay_ctx *ctx)
 {
 	strbuf_release(&ctx->current_fixups);
 	strbuf_release(&ctx->message);
+	strbuf_release(&ctx->config_parameters);
 }
 
 void replay_opts_release(struct replay_opts *opts)
@@ -1107,6 +1114,27 @@ static int run_command_silent_on_success(struct child_process *cmd)
 	return rc;
 }
 
+/*
+ * A sequence runs auto maintenance once it is done, not from every command
+ * it spawns along the way: their background "rerere gc" or repack would
+ * race the sequencer for locks and files it still holds.
+ */
+static void disable_auto_maintenance(struct replay_opts *opts,
+				     struct child_process *cmd)
+{
+	struct strbuf *params = &opts->ctx->config_parameters;
+
+	if (!params->len) {
+		const char *old = getenv(CONFIG_DATA_ENVIRONMENT);
+
+		if (old && *old)
+			strbuf_addstr(params, old);
+		git_config_append_parameter(params, "maintenance.auto", "false");
+		git_config_append_parameter(params, "gc.auto", "0");
+	}
+	strvec_pushf(&cmd->env, "%s=%s", CONFIG_DATA_ENVIRONMENT, params->buf);
+}
+
 /*
  * If we are cherry-pick, and if the merge did not result in
  * hand-editing, we will hit this commit and inherit the original
@@ -1148,6 +1176,7 @@ static int run_git_commit(const char *defmsg,
 			     author_date_from_env(&cmd.env));
 	if (opts->ignore_date)
 		strvec_push(&cmd.env, "GIT_AUTHOR_DATE=");
+	disable_auto_maintenance(opts, &cmd);
 
 	strvec_push(&cmd.args, "commit");
 
@@ -3924,16 +3953,18 @@ static int error_failed_squash(struct repository *r,
 	return error_with_patch(r, commit, subject, subject_len, opts, 1, 1);
 }
 
-static int do_exec(struct repository *r, const char *command_line, int quiet)
+static int do_exec(struct repository *r, const char *command_line,
+		   struct replay_opts *opts)
 {
 	struct child_process cmd = CHILD_PROCESS_INIT;
 	int dirty, status;
 
-	if (!quiet)
+	if (!opts->quiet)
 		fprintf(stderr, _("Executing: %s\n"), command_line);
 	cmd.use_shell = 1;
 	strvec_push(&cmd.args, command_line);
 	strvec_push(&cmd.env, "GIT_CHERRY_PICK_HELP");
+	disable_auto_maintenance(opts, &cmd);
 	status = run_command(&cmd);
 
 	/* force re-reading of the cache */
@@ -4342,6 +4373,7 @@ static int do_merge(struct repository *r,
 				     author_date_from_env(&cmd.env));
 		if (opts->ignore_date)
 			strvec_push(&cmd.env, "GIT_AUTHOR_DATE=");
+		disable_auto_maintenance(opts, &cmd);
 
 		cmd.git_cmd = 1;
 		strvec_push(&cmd.args, "merge");
@@ -5158,7 +5190,7 @@ static int pick_commits(struct repository *r,
 			if (!opts->verbose)
 				term_clear_line();
 			*end_of_arg = '\0';
-			res = do_exec(r, arg, opts->quiet);
+			res = do_exec(r, arg, opts);
 			*end_of_arg = saved;
 
 			if (res) {
@@ -5335,6 +5367,7 @@ static int continue_single_pick(struct repository *r, struct replay_opts *opts)
 		return error(_("no cherry-pick or revert in progress"));
 
 	cmd.git_cmd = 1;
+	disable_auto_maintenance(opts, &cmd);
 	strvec_push(&cmd.args, "commit");
 
 	/*
diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh
index 2c34cf8a01..cf6d20ce79 100755
--- a/t/t3418-rebase-continue.sh
+++ b/t/t3418-rebase-continue.sh
@@ -403,4 +403,22 @@ test_expect_success 'rebase runs auto maintenance at its end' '
 	test_subcommand_flex git maintenance run --auto <finish.txt
 '
 
+test_expect_success 'rebase spawns no auto maintenance before its end' '
+	git checkout -b two-conflicts topic &&
+	test_commit F2-again F2 222 &&
+	test_must_fail git rebase -x "git commit --allow-empty -m exec" main &&
+	echo resolved >F2 &&
+	git add F2 &&
+	test_must_fail env GIT_TRACE2_EVENT="$(pwd)/mid.txt" \
+		git rebase --continue &&
+	test_subcommand_flex git commit <mid.txt &&
+	test_subcommand_flex ! git maintenance run --auto <mid.txt &&
+	echo resolved >F2 &&
+	git add F2 &&
+	GIT_TRACE2_EVENT="$(pwd)/end.txt" git rebase --continue &&
+	test_subcommand_flex git maintenance run --auto <end.txt &&
+	grep "\"child_start\".*\"maintenance\"" end.txt >maintenance &&
+	test_line_count = 1 maintenance
+'
+
 test_done
diff --git a/t/t3510-cherry-pick-sequence.sh b/t/t3510-cherry-pick-sequence.sh
index 304981ccd6..57a77d91bd 100755
--- a/t/t3510-cherry-pick-sequence.sh
+++ b/t/t3510-cherry-pick-sequence.sh
@@ -731,4 +731,21 @@ test_expect_success 'cherry-pick runs auto maintenance once it is done' '
 	test_line_count = 1 maintenance
 '
 
+test_expect_success 'cherry-pick spawns no auto maintenance before it is done' '
+	pristine_detach initial &&
+	test_must_fail git cherry-pick base..anotherpick &&
+	echo resolved >foo &&
+	git add foo &&
+	test_must_fail env GIT_TRACE2_EVENT="$(pwd)/mid.txt" \
+		git cherry-pick --continue &&
+	test_subcommand_flex git commit <mid.txt &&
+	test_subcommand_flex ! git maintenance run --auto <mid.txt &&
+	echo d >foo &&
+	git add foo &&
+	GIT_TRACE2_EVENT="$(pwd)/end.txt" git cherry-pick --continue &&
+	test_subcommand_flex git commit <end.txt &&
+	grep "\"child_start\".*\"maintenance\"" end.txt >maintenance &&
+	test_line_count = 1 maintenance
+'
+
 test_done
-- 
gitgitgadget

  parent reply	other threads:[~2026-09-04 15:51 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-04  7:53 [PATCH 0/2] sequencer: leave auto maintenance to the end of a rebase Thomas Bachem via GitGitGadget
2026-09-04  7:53 ` [PATCH 1/2] sequencer: run auto maintenance once a rebase is done Thomas Bachem via GitGitGadget
2026-09-04 15:03   ` Phillip Wood
2026-09-04  7:53 ` [PATCH 2/2] sequencer: keep auto maintenance out of the commands a rebase spawns Thomas Bachem via GitGitGadget
2026-09-04 15:03   ` Phillip Wood
2026-09-04 15:55     ` Thomas Bachem
2026-09-04 15:51 ` [PATCH v2 0/3] sequencer: leave auto maintenance to the end of a sequence Thomas Bachem via GitGitGadget
2026-09-04 15:51   ` [PATCH v2 1/3] config: add git_config_append_parameter() Thomas Bachem via GitGitGadget
2026-09-07  8:14     ` Patrick Steinhardt
2026-09-07 13:24       ` Phillip Wood
2026-09-07 14:47         ` Patrick Steinhardt
2026-09-07 16:37       ` Thomas Bachem
2026-09-04 15:51   ` [PATCH v2 2/3] sequencer: run auto maintenance once a sequence is done Thomas Bachem via GitGitGadget
2026-09-07  8:14     ` Patrick Steinhardt
2026-09-07 16:35       ` Thomas Bachem
2026-09-08  5:50         ` Patrick Steinhardt
2026-09-08  7:46           ` Thomas Bachem
2026-09-07 13:25     ` Phillip Wood
2026-09-07 16:36       ` Thomas Bachem
2026-09-07 16:40         ` Phillip Wood
2026-09-04 15:51   ` Thomas Bachem via GitGitGadget [this message]
2026-09-04 21:21     ` [PATCH v2 3/3] sequencer: keep auto maintenance out of the commands a sequence spawns Junio C Hamano
2026-09-05  5:42       ` Thomas Bachem
2026-09-07  8:14     ` Patrick Steinhardt
2026-09-07 16:35       ` Thomas Bachem
2026-09-07 13:24     ` Phillip Wood
2026-09-07 16:37       ` Thomas Bachem
2026-09-08 10:28 ` [PATCH v3 0/3] sequencer: leave auto maintenance to the end of a sequence Thomas Bachem via GitGitGadget
2026-09-08 10:28   ` [PATCH v3 1/3] config: add git_config_append_parameter() Thomas Bachem via GitGitGadget
2026-09-08 10:28   ` [PATCH v3 2/3] rebase, cherry-pick, revert: run auto maintenance when done Thomas Bachem via GitGitGadget
2026-09-08 10:28   ` [PATCH v3 3/3] sequencer: disable auto maintenance in spawned commands Thomas Bachem via GitGitGadget
2026-09-08 15:53   ` [PATCH v3 0/3] sequencer: leave auto maintenance to the end of a sequence Junio C Hamano
2026-09-08 19:38     ` Kristoffer Haugsbakk
2026-09-09  5:57     ` Patrick Steinhardt
2026-09-10  8:25     ` Thomas Bachem
2026-09-09  8:25 ` [PATCH v4 " Thomas Bachem via GitGitGadget
2026-09-09  8:25   ` [PATCH v4 1/3] config: add git_config_append_parameter() Thomas Bachem via GitGitGadget
2026-09-11  7:34     ` Patrick Steinhardt
2026-09-09  8:25   ` [PATCH v4 2/3] rebase, cherry-pick, revert: run auto maintenance when done Thomas Bachem via GitGitGadget
2026-09-11  7:34     ` Patrick Steinhardt
2026-09-09  8:25   ` [PATCH v4 3/3] sequencer: disable auto maintenance in spawned commands Thomas Bachem via GitGitGadget
2026-09-09 15:40     ` Phillip Wood

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=9a6fc0427a8bc7e7abcc0518214b1dafc2efaa6a.1788537086.git.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=johannes.schindelin@gmx.de \
    --cc=mail@thomasbachem.com \
    --cc=phillip.wood@dunelm.org.uk \
    --cc=ps@pks.im \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.