* [PATCH 0/1] rebase: add --[no-]edit to --continue
@ 2026-07-21 14:04 Hugo Sales
2026-07-21 14:04 ` [PATCH 1/1] " Hugo Sales
2026-07-21 18:04 ` [PATCH 0/1] " Junio C Hamano
0 siblings, 2 replies; 5+ messages in thread
From: Hugo Sales @ 2026-07-21 14:04 UTC (permalink / raw)
To: git; +Cc: Hugo Sales
When a rebase stops for conflicts and the user runs `git rebase --continue`, the
merge backend opens $EDITOR so the commit message can be revised. That is often
useful, but not always: sometimes the user only wants to keep the message that
is already there.
This series adds:
- `git rebase --continue --no-edit` to commit without opening an editor
- `rebase.noEdit` to make that the default on continue
- `git rebase --continue --edit` to override `rebase.noEdit`
The command-line flags apply only to the current `--continue` invocation, not to
later picks in the same rebase.
Tests are added in t3436. I also ran all tests locally.
Hugo Sales (1):
rebase: add --[no-]edit to --continue
Documentation/config/rebase.adoc | 6 ++++
Documentation/git-rebase.adoc | 17 +++++++++--
builtin/rebase.c | 29 ++++++++++++++++--
sequencer.c | 29 +++++++++++++++++-
t/t3436-rebase-more-options.sh | 52 ++++++++++++++++++++++++++++++++
5 files changed, 126 insertions(+), 7 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/1] rebase: add --[no-]edit to --continue
2026-07-21 14:04 [PATCH 0/1] rebase: add --[no-]edit to --continue Hugo Sales
@ 2026-07-21 14:04 ` Hugo Sales
2026-07-21 18:04 ` [PATCH 0/1] " Junio C Hamano
1 sibling, 0 replies; 5+ messages in thread
From: Hugo Sales @ 2026-07-21 14:04 UTC (permalink / raw)
To: git
Cc: Hugo Sales, Phillip Wood, Junio C Hamano,
Ævar Arnfjörð Bjarmason, Patrick Steinhardt,
Elijah Newren
Allow skipping the editor when continuing after resolving conflicts,
via --no-edit or the rebase.noEdit configuration variable. The --edit
option overrides rebase.noEdit when both are set.
Signed-off-by: Hugo Sales <hugo@hsal.es>
---
Documentation/config/rebase.adoc | 6 ++++
Documentation/git-rebase.adoc | 17 +++++++++--
builtin/rebase.c | 29 ++++++++++++++++--
sequencer.c | 29 +++++++++++++++++-
t/t3436-rebase-more-options.sh | 52 ++++++++++++++++++++++++++++++++
5 files changed, 126 insertions(+), 7 deletions(-)
diff --git a/Documentation/config/rebase.adoc b/Documentation/config/rebase.adoc
index c6187ab28b..321ab8b529 100644
--- a/Documentation/config/rebase.adoc
+++ b/Documentation/config/rebase.adoc
@@ -62,6 +62,12 @@ instead of:
+
Defaults to false.
+rebase.noEdit::
+ When set to true, `git rebase --continue` uses the commit message
+ without launching $EDITOR, as if `--no-edit` were given. The
+ `--edit` option to `git rebase --continue` overrides this setting.
+ Defaults to false.
+
rebase.rescheduleFailedExec::
Automatically reschedule `exec` commands that failed. This only makes
sense in interactive mode (or when an `--exec` option was provided).
diff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc
index f6c22d1598..cc0a69b5a5 100644
--- a/Documentation/git-rebase.adoc
+++ b/Documentation/git-rebase.adoc
@@ -181,6 +181,16 @@ including not with each other:
--continue::
Restart the rebasing process after having resolved a merge conflict.
++
+-e::
+--edit::
+--no-edit::
+ With `--continue`, edit or do not edit the commit message,
+ respectively. By default, the configured $EDITOR is opened so you
+ can update the commit message after resolving conflicts.
+ `--no-edit` reuses the existing message without launching an
+ editor. The `rebase.noEdit` configuration variable can be used to
+ enable `--no-edit` by default; `--edit` overrides that setting.
--skip::
Restart the rebasing process by skipping the current patch.
@@ -783,9 +793,10 @@ Commit Rewording
When a conflict occurs while rebasing, rebase stops and asks the user
to resolve. Since the user may need to make notable changes while
resolving conflicts, after conflicts are resolved and the user has run
-`git rebase --continue`, the rebase should open an editor and ask the
-user to update the commit message. The 'merge' backend does this, while
-the 'apply' backend blindly applies the original commit message.
+`git rebase --continue`, the rebase opens an editor and asks the
+user to update the commit message, unless `rebase.noEdit` is set or
+`--no-edit` is passed to `--continue`. The 'merge' backend does this,
+while the 'apply' backend blindly applies the original commit message.
Miscellaneous differences
~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 10a306310c..5827b20baf 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -43,7 +43,7 @@ static char const * const builtin_rebase_usage[] = {
"[--onto <newbase> | --keep-base] [<upstream> [<branch>]]"),
N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
"--root [<branch>]"),
- "git rebase --continue | --abort | --skip | --edit-todo",
+ "git rebase --continue [--[no-]edit] | --abort | --skip | --edit-todo",
NULL
};
@@ -135,6 +135,8 @@ struct rebase_options {
int config_autosquash;
int config_rebase_merges;
int config_update_refs;
+ int config_no_edit;
+ int edit;
};
#define REBASE_OPTIONS_INIT { \
@@ -156,6 +158,8 @@ struct rebase_options {
.update_refs = -1, \
.config_update_refs = -1, \
.strategy_opts = STRING_LIST_INIT_NODUP,\
+ .config_no_edit = -1, \
+ .edit = -1, \
}
static void rebase_options_release(struct rebase_options *opts)
@@ -215,6 +219,13 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)
replay.have_squash_onto = 1;
}
+ if (opts->action == ACTION_CONTINUE) {
+ if (opts->edit >= 0)
+ replay.edit = opts->edit;
+ else if (opts->config_no_edit > 0)
+ replay.edit = 0;
+ }
+
return replay;
}
@@ -841,6 +852,11 @@ static int rebase_config(const char *var, const char *value,
return 0;
}
+ if (!strcmp(var, "rebase.noedit")) {
+ opts->config_no_edit = git_config_bool(var, value);
+ return 0;
+ }
+
if (!strcmp(var, "rebase.forkpoint")) {
opts->fork_point = git_config_bool(var, value) ? -1 : 0;
return 0;
@@ -1171,6 +1187,8 @@ int cmd_rebase(int argc,
ACTION_CONTINUE),
OPT_CMDMODE(0, "skip", &options.action,
N_("skip current patch and continue"), ACTION_SKIP),
+ OPT_BOOL('e', "edit", &options.edit,
+ N_("edit the commit message")),
OPT_CMDMODE(0, "abort", &options.action,
N_("abort and check out the original branch"),
ACTION_ABORT),
@@ -1311,10 +1329,15 @@ int cmd_rebase(int argc,
"which is no longer supported; use 'merges' instead"));
if (options.action != ACTION_NONE && total_argc != 2) {
- usage_with_options(builtin_rebase_usage,
- builtin_rebase_options);
+ if (options.action != ACTION_CONTINUE ||
+ options.edit < 0 || total_argc != 3)
+ usage_with_options(builtin_rebase_usage,
+ builtin_rebase_options);
}
+ if (options.edit >= 0 && options.action != ACTION_CONTINUE)
+ die(_("--edit and --no-edit can only be used with --continue"));
+
if (argc > 2)
usage_with_options(builtin_rebase_usage,
builtin_rebase_options);
diff --git a/sequencer.c b/sequencer.c
index 1355a99a09..be2945b12d 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -2211,6 +2211,25 @@ static int should_edit(struct replay_opts *opts) {
return opts->edit;
}
+static int should_edit_rebase_continue(struct replay_opts *opts)
+{
+ if (opts->edit < 0)
+ return 1;
+ return opts->edit;
+}
+
+static void finalize_continue_edit_flags(struct replay_opts *opts,
+ unsigned int *flags)
+{
+ if (*flags & CLEANUP_MSG)
+ return;
+
+ if (should_edit_rebase_continue(opts))
+ *flags |= EDIT_MSG;
+ else
+ *flags &= ~EDIT_MSG;
+}
+
static void refer_to_commit(struct repository *r, struct strbuf *msgbuf,
const struct commit *commit,
bool use_commit_reference)
@@ -5281,7 +5300,7 @@ static int commit_staged_changes(struct repository *r,
struct todo_list *todo_list)
{
struct replay_ctx *ctx = opts->ctx;
- unsigned int flags = ALLOW_EMPTY | EDIT_MSG;
+ unsigned int flags = ALLOW_EMPTY;
unsigned int final_fixup = 0, is_clean;
struct strbuf rev = STRBUF_INIT;
const char *reflog_action = reflog_message(opts, "continue", NULL);
@@ -5446,6 +5465,8 @@ static int commit_staged_changes(struct repository *r,
}
}
+ finalize_continue_edit_flags(opts, &flags);
+
if (run_git_commit(final_fixup ? NULL : rebase_path_message(),
reflog_action, opts, flags)) {
ret = error(_("could not commit staged changes."));
@@ -5503,6 +5524,12 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts)
res = -1;
goto release_todo_list;
}
+
+ /*
+ * Command-line --[no-]edit applies only to this
+ * --continue invocation, not to subsequent picks.
+ */
+ opts->edit = -1;
} else if (!file_exists(get_todo_path(opts)))
return continue_single_pick(r, opts);
else if ((res = read_populate_todo(r, &todo_list, opts)))
diff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh
index 94671d3c46..c84c6717ab 100755
--- a/t/t3436-rebase-more-options.sh
+++ b/t/t3436-rebase-more-options.sh
@@ -201,6 +201,58 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '
test_atime_is_ignored -2
'
+test_expect_success '--no-edit on continue uses existing commit message' '
+ git checkout commit2 &&
+ test_must_fail git rebase -m --onto commit2^^ commit2^ &&
+ echo resolved >foo &&
+ git add foo &&
+ write_script fail-if-editor-invoked <<-\EOF &&
+ echo editor invoked >&2
+ exit 1
+ EOF
+ GIT_EDITOR=./fail-if-editor-invoked git rebase --continue --no-edit &&
+ git log --format=%s -1 >actual &&
+ echo commit2 >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success '--no-edit cannot be used when starting a rebase' '
+ test_must_fail git rebase --no-edit -m main side 2>err &&
+ test_grep "only be used with --continue" err
+'
+
+test_expect_success 'rebase.noEdit skips editor on continue' '
+ git config rebase.noEdit true &&
+ git checkout commit2 &&
+ test_must_fail git rebase -m --onto commit2^^ commit2^ &&
+ echo resolved >foo &&
+ git add foo &&
+ write_script fail-if-editor-invoked <<-\EOF &&
+ echo editor invoked >&2
+ exit 1
+ EOF
+ GIT_EDITOR=./fail-if-editor-invoked git rebase --continue &&
+ git log --format=%s -1 >actual &&
+ echo commit2 >expect &&
+ test_cmp expect actual
+'
+
+test_expect_success '--edit on continue overrides rebase.noEdit' '
+ git config rebase.noEdit true &&
+ git checkout commit2 &&
+ test_must_fail git rebase -m --onto commit2^^ commit2^ &&
+ echo resolved >foo &&
+ git add foo &&
+ (
+ set_fake_editor &&
+ FAKE_COMMIT_MESSAGE="edited on continue" \
+ git rebase --continue --edit
+ ) &&
+ test_write_lines "edited on continue" "" >expect &&
+ git log --format=%B -1 >actual &&
+ test_cmp expect actual
+'
+
# This must be the last test in this file
test_expect_success '$EDITOR and friends are unchanged' '
test_editor_unchanged
--
2.54.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/1] rebase: add --[no-]edit to --continue
2026-07-21 14:04 [PATCH 0/1] rebase: add --[no-]edit to --continue Hugo Sales
2026-07-21 14:04 ` [PATCH 1/1] " Hugo Sales
@ 2026-07-21 18:04 ` Junio C Hamano
2026-07-22 13:39 ` Phillip Wood
1 sibling, 1 reply; 5+ messages in thread
From: Junio C Hamano @ 2026-07-21 18:04 UTC (permalink / raw)
To: Hugo Sales; +Cc: git
Hugo Sales <hugo@hsal.es> writes:
> When a rebase stops for conflicts and the user runs `git rebase --continue`, the
> merge backend opens $EDITOR so the commit message can be revised. That is often
> useful, but not always: sometimes the user only wants to keep the message that
> is already there.
>
> This series adds:
>
> - `git rebase --continue --no-edit` to commit without opening an editor
Meh. "GIT_SEQUENCE_EDITOR=: git rebase --continue" is your friend ;-)
> - `rebase.noEdit` to make that the default on continue
> - `git rebase --continue --edit` to override `rebase.noEdit`
The new 'rebase.noEdit' configuration is especially concerning. It
encourages users to assume by default that their rebase sessions
will not produce notable changes worth recording in the commit logs.
A few immediate edge cases come to mind:
- What if 'rebase -i' stops to give control back to the user for
reasons other than a merge conflict? If the user chose 'edit',
their original intent was to modify both the commit message and
the content. With 'rebase.noEdit' enabled, would they now have
to remember to pass '--edit' when continuing? Does the answer
depend on whether the 'edit' step resulted in a merge conflict?
- What if the user chose 'reword', which is an explicit signal to
update the commit message, but 'rebase.noEdit' is enabled? If
the rebase does not stop with a conflict, it might open the
editor regardless of the configuration. But if a conflict does
occur and requires manual resolution, will the user still need to
remember to pass '--edit' when continuing?
The proposed tests only cover the code path where control returns to
the user due to a conflict. This is understandable since that
scenario was your primary motivation. However, they do not verify
what happens when there are no conflicts but the user explicitly
intended to edit the message from the start. You may want to expand
the test coverage to address these scenarios (and potentially
others, as this is not an exhaustive list).
Thanks.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 0/1] rebase: add --[no-]edit to --continue
2026-07-21 18:04 ` [PATCH 0/1] " Junio C Hamano
@ 2026-07-22 13:39 ` Phillip Wood
2026-07-22 15:36 ` Junio C Hamano
0 siblings, 1 reply; 5+ messages in thread
From: Phillip Wood @ 2026-07-22 13:39 UTC (permalink / raw)
To: Junio C Hamano, Hugo Sales; +Cc: git
On 21/07/2026 19:04, Junio C Hamano wrote:
> Hugo Sales <hugo@hsal.es> writes:
>
>> When a rebase stops for conflicts and the user runs `git rebase --continue`, the
>> merge backend opens $EDITOR so the commit message can be revised. That is often
>> useful, but not always: sometimes the user only wants to keep the message that
>> is already there.
>>
>> This series adds:
>>
>> - `git rebase --continue --no-edit` to commit without opening an editor
>
> Meh. "GIT_SEQUENCE_EDITOR=: git rebase --continue" is your friend ;-)
Do you mean "GIT_EDITOR=:"? The sequence editor is only relevant for
editing the todo list. The last time this came up [1] I shared an alias
that only suppresses the editor if HEAD has not changed since the user
continued the rebase, but that does not stop the user suppressing the
editor when continuing a "reword" command. I share the concerns you
listed below about this patch in its current form.
Thanks
Phillip
[1]
https://lore.kernel.org/git/fbf859ca-43f4-433e-b111-377aa60f1947@gmail.com
>> - `rebase.noEdit` to make that the default on continue
>> - `git rebase --continue --edit` to override `rebase.noEdit`
>
> The new 'rebase.noEdit' configuration is especially concerning. It
> encourages users to assume by default that their rebase sessions
> will not produce notable changes worth recording in the commit logs.
>
> A few immediate edge cases come to mind:
>
> - What if 'rebase -i' stops to give control back to the user for
> reasons other than a merge conflict? If the user chose 'edit',
> their original intent was to modify both the commit message and
> the content. With 'rebase.noEdit' enabled, would they now have
> to remember to pass '--edit' when continuing? Does the answer
> depend on whether the 'edit' step resulted in a merge conflict?
>
> - What if the user chose 'reword', which is an explicit signal to
> update the commit message, but 'rebase.noEdit' is enabled? If
> the rebase does not stop with a conflict, it might open the
> editor regardless of the configuration. But if a conflict does
> occur and requires manual resolution, will the user still need to
> remember to pass '--edit' when continuing?
>
> The proposed tests only cover the code path where control returns to
> the user due to a conflict. This is understandable since that
> scenario was your primary motivation. However, they do not verify
> what happens when there are no conflicts but the user explicitly
> intended to edit the message from the start. You may want to expand
> the test coverage to address these scenarios (and potentially
> others, as this is not an exhaustive list).
>
> Thanks.
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 0/1] rebase: add --[no-]edit to --continue
2026-07-22 13:39 ` Phillip Wood
@ 2026-07-22 15:36 ` Junio C Hamano
0 siblings, 0 replies; 5+ messages in thread
From: Junio C Hamano @ 2026-07-22 15:36 UTC (permalink / raw)
To: Phillip Wood; +Cc: Hugo Sales, git
Phillip Wood <phillip.wood123@gmail.com> writes:
> On 21/07/2026 19:04, Junio C Hamano wrote:
>> Hugo Sales <hugo@hsal.es> writes:
>>
>>> When a rebase stops for conflicts and the user runs `git rebase --continue`, the
>>> merge backend opens $EDITOR so the commit message can be revised. That is often
>>> useful, but not always: sometimes the user only wants to keep the message that
>>> is already there.
>>>
>>> This series adds:
>>>
>>> - `git rebase --continue --no-edit` to commit without opening an editor
>>
>> Meh. "GIT_SEQUENCE_EDITOR=: git rebase --continue" is your friend ;-)
>
> Do you mean "GIT_EDITOR=:"? The sequence editor is only relevant for
Oh, absolutely. I made a last minute change s/_EDITOR/SEQUENCE_&/
before sending it out, without realizing that I made a totally
unnecessary change X-<.
Thanks for spotting.
> editing the todo list.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-22 15:36 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-21 14:04 [PATCH 0/1] rebase: add --[no-]edit to --continue Hugo Sales
2026-07-21 14:04 ` [PATCH 1/1] " Hugo Sales
2026-07-21 18:04 ` [PATCH 0/1] " Junio C Hamano
2026-07-22 13:39 ` Phillip Wood
2026-07-22 15:36 ` Junio C Hamano
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.