{"thread":{"id":"66045","subject":"[PATCH 0/1] rebase: add --[no-]edit to --continue","startedAt":"2026-07-21T14:05:00Z","lastAt":"2026-07-22T15:36:06Z","messageCount":5,"participants":["Hugo Sales","Junio C Hamano","Phillip Wood"],"isPatch":true,"patchVersion":1,"patchTotal":1},"messages":[{"id":"548722","messageId":"20260721140443.1809379-1-hugo@hsal.es","threadId":"66045","inReplyTo":null,"subject":"[PATCH 0/1] rebase: add --[no-]edit to --continue","fromName":"Hugo Sales","fromEmail":"hugo@hsal.es","sentAt":"2026-07-21T14:04:41Z","receivedAt":"2026-07-21T14:05:00Z","isPatch":true,"body":"When a rebase stops for conflicts and the user runs `git rebase --continue`, the\nmerge backend opens $EDITOR so the commit message can be revised. That is often\nuseful, but not always: sometimes the user only wants to keep the message that\nis already there.\n\nThis series adds:\n\n- `git rebase --continue --no-edit` to commit without opening an editor\n- `rebase.noEdit` to make that the default on continue\n- `git rebase --continue --edit` to override `rebase.noEdit`\n\nThe command-line flags apply only to the current `--continue` invocation, not to\nlater picks in the same rebase.\n\nTests are added in t3436. I also ran all tests locally.\n\nHugo Sales (1):\n  rebase: add --[no-]edit to --continue\n\n Documentation/config/rebase.adoc |  6 ++++\n Documentation/git-rebase.adoc    | 17 +++++++++--\n builtin/rebase.c                 | 29 ++++++++++++++++--\n sequencer.c                      | 29 +++++++++++++++++-\n t/t3436-rebase-more-options.sh   | 52 ++++++++++++++++++++++++++++++++\n 5 files changed, 126 insertions(+), 7 deletions(-)\n\n-- \n2.54.0\n"},{"id":"548723","messageId":"20260721140443.1809379-2-hugo@hsal.es","threadId":"66045","inReplyTo":"20260721140443.1809379-1-hugo@hsal.es","subject":"[PATCH 1/1] rebase: add --[no-]edit to --continue","fromName":"Hugo Sales","fromEmail":"hugo@hsal.es","sentAt":"2026-07-21T14:04:42Z","receivedAt":"2026-07-21T14:05:03Z","isPatch":true,"body":"Allow skipping the editor when continuing after resolving conflicts,\nvia --no-edit or the rebase.noEdit configuration variable. The --edit\noption overrides rebase.noEdit when both are set.\n\nSigned-off-by: Hugo Sales <hugo@hsal.es>\n---\n Documentation/config/rebase.adoc |  6 ++++\n Documentation/git-rebase.adoc    | 17 +++++++++--\n builtin/rebase.c                 | 29 ++++++++++++++++--\n sequencer.c                      | 29 +++++++++++++++++-\n t/t3436-rebase-more-options.sh   | 52 ++++++++++++++++++++++++++++++++\n 5 files changed, 126 insertions(+), 7 deletions(-)\n\ndiff --git a/Documentation/config/rebase.adoc b/Documentation/config/rebase.adoc\nindex c6187ab28b..321ab8b529 100644\n--- a/Documentation/config/rebase.adoc\n+++ b/Documentation/config/rebase.adoc\n@@ -62,6 +62,12 @@ instead of:\n +\n Defaults to false.\n \n+rebase.noEdit::\n+\tWhen set to true, `git rebase --continue` uses the commit message\n+\twithout launching $EDITOR, as if `--no-edit` were given.  The\n+\t`--edit` option to `git rebase --continue` overrides this setting.\n+\tDefaults to false.\n+\n rebase.rescheduleFailedExec::\n \tAutomatically reschedule `exec` commands that failed. This only makes\n \tsense in interactive mode (or when an `--exec` option was provided).\ndiff --git a/Documentation/git-rebase.adoc b/Documentation/git-rebase.adoc\nindex f6c22d1598..cc0a69b5a5 100644\n--- a/Documentation/git-rebase.adoc\n+++ b/Documentation/git-rebase.adoc\n@@ -181,6 +181,16 @@ including not with each other:\n \n --continue::\n \tRestart the rebasing process after having resolved a merge conflict.\n++\n+-e::\n+--edit::\n+--no-edit::\n+\tWith `--continue`, edit or do not edit the commit message,\n+\trespectively. By default, the configured $EDITOR is opened so you\n+\tcan update the commit message after resolving conflicts.\n+\t`--no-edit` reuses the existing message without launching an\n+\teditor. The `rebase.noEdit` configuration variable can be used to\n+\tenable `--no-edit` by default; `--edit` overrides that setting.\n \n --skip::\n \tRestart the rebasing process by skipping the current patch.\n@@ -783,9 +793,10 @@ Commit Rewording\n When a conflict occurs while rebasing, rebase stops and asks the user\n to resolve.  Since the user may need to make notable changes while\n resolving conflicts, after conflicts are resolved and the user has run\n-`git rebase --continue`, the rebase should open an editor and ask the\n-user to update the commit message.  The 'merge' backend does this, while\n-the 'apply' backend blindly applies the original commit message.\n+`git rebase --continue`, the rebase opens an editor and asks the\n+user to update the commit message, unless `rebase.noEdit` is set or\n+`--no-edit` is passed to `--continue`.  The 'merge' backend does this,\n+while the 'apply' backend blindly applies the original commit message.\n \n Miscellaneous differences\n ~~~~~~~~~~~~~~~~~~~~~~~~~\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 10a306310c..5827b20baf 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -43,7 +43,7 @@ static char const * const builtin_rebase_usage[] = {\n \t\t\"[--onto <newbase> | --keep-base] [<upstream> [<branch>]]\"),\n \tN_(\"git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] \"\n \t\t\"--root [<branch>]\"),\n-\t\"git rebase --continue | --abort | --skip | --edit-todo\",\n+\t\"git rebase --continue [--[no-]edit] | --abort | --skip | --edit-todo\",\n \tNULL\n };\n \n@@ -135,6 +135,8 @@ struct rebase_options {\n \tint config_autosquash;\n \tint config_rebase_merges;\n \tint config_update_refs;\n+\tint config_no_edit;\n+\tint edit;\n };\n \n #define REBASE_OPTIONS_INIT {\t\t\t  \t\\\n@@ -156,6 +158,8 @@ struct rebase_options {\n \t\t.update_refs = -1,                      \\\n \t\t.config_update_refs = -1,               \\\n \t\t.strategy_opts = STRING_LIST_INIT_NODUP,\\\n+\t\t.config_no_edit = -1,                   \\\n+\t\t.edit = -1,                             \\\n \t}\n \n static void rebase_options_release(struct rebase_options *opts)\n@@ -215,6 +219,13 @@ static struct replay_opts get_replay_opts(const struct rebase_options *opts)\n \t\treplay.have_squash_onto = 1;\n \t}\n \n+\tif (opts->action == ACTION_CONTINUE) {\n+\t\tif (opts->edit >= 0)\n+\t\t\treplay.edit = opts->edit;\n+\t\telse if (opts->config_no_edit > 0)\n+\t\t\treplay.edit = 0;\n+\t}\n+\n \treturn replay;\n }\n \n@@ -841,6 +852,11 @@ static int rebase_config(const char *var, const char *value,\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"rebase.noedit\")) {\n+\t\topts->config_no_edit = git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n+\n \tif (!strcmp(var, \"rebase.forkpoint\")) {\n \t\topts->fork_point = git_config_bool(var, value) ? -1 : 0;\n \t\treturn 0;\n@@ -1171,6 +1187,8 @@ int cmd_rebase(int argc,\n \t\t\t    ACTION_CONTINUE),\n \t\tOPT_CMDMODE(0, \"skip\", &options.action,\n \t\t\t    N_(\"skip current patch and continue\"), ACTION_SKIP),\n+\t\tOPT_BOOL('e', \"edit\", &options.edit,\n+\t\t\t N_(\"edit the commit message\")),\n \t\tOPT_CMDMODE(0, \"abort\", &options.action,\n \t\t\t    N_(\"abort and check out the original branch\"),\n \t\t\t    ACTION_ABORT),\n@@ -1311,10 +1329,15 @@ int cmd_rebase(int argc,\n \t\t\t\"which is no longer supported; use 'merges' instead\"));\n \n \tif (options.action != ACTION_NONE && total_argc != 2) {\n-\t\tusage_with_options(builtin_rebase_usage,\n-\t\t\t\t   builtin_rebase_options);\n+\t\tif (options.action != ACTION_CONTINUE ||\n+\t\t    options.edit < 0 || total_argc != 3)\n+\t\t\tusage_with_options(builtin_rebase_usage,\n+\t\t\t\t\t   builtin_rebase_options);\n \t}\n \n+\tif (options.edit >= 0 && options.action != ACTION_CONTINUE)\n+\t\tdie(_(\"--edit and --no-edit can only be used with --continue\"));\n+\n \tif (argc > 2)\n \t\tusage_with_options(builtin_rebase_usage,\n \t\t\t\t   builtin_rebase_options);\ndiff --git a/sequencer.c b/sequencer.c\nindex 1355a99a09..be2945b12d 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -2211,6 +2211,25 @@ static int should_edit(struct replay_opts *opts) {\n \treturn opts->edit;\n }\n \n+static int should_edit_rebase_continue(struct replay_opts *opts)\n+{\n+\tif (opts->edit < 0)\n+\t\treturn 1;\n+\treturn opts->edit;\n+}\n+\n+static void finalize_continue_edit_flags(struct replay_opts *opts,\n+\t\t\t\t\t unsigned int *flags)\n+{\n+\tif (*flags & CLEANUP_MSG)\n+\t\treturn;\n+\n+\tif (should_edit_rebase_continue(opts))\n+\t\t*flags |= EDIT_MSG;\n+\telse\n+\t\t*flags &= ~EDIT_MSG;\n+}\n+\n static void refer_to_commit(struct repository *r, struct strbuf *msgbuf,\n \t\t\t    const struct commit *commit,\n \t\t\t    bool use_commit_reference)\n@@ -5281,7 +5300,7 @@ static int commit_staged_changes(struct repository *r,\n \t\t\t\t struct todo_list *todo_list)\n {\n \tstruct replay_ctx *ctx = opts->ctx;\n-\tunsigned int flags = ALLOW_EMPTY | EDIT_MSG;\n+\tunsigned int flags = ALLOW_EMPTY;\n \tunsigned int final_fixup = 0, is_clean;\n \tstruct strbuf rev = STRBUF_INIT;\n \tconst char *reflog_action = reflog_message(opts, \"continue\", NULL);\n@@ -5446,6 +5465,8 @@ static int commit_staged_changes(struct repository *r,\n \t\t}\n \t}\n \n+\tfinalize_continue_edit_flags(opts, &flags);\n+\n \tif (run_git_commit(final_fixup ? NULL : rebase_path_message(),\n \t\t\t   reflog_action, opts, flags)) {\n \t\tret = error(_(\"could not commit staged changes.\"));\n@@ -5503,6 +5524,12 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts)\n \t\t\tres = -1;\n \t\t\tgoto release_todo_list;\n \t\t}\n+\n+\t\t/*\n+\t\t * Command-line --[no-]edit applies only to this\n+\t\t * --continue invocation, not to subsequent picks.\n+\t\t */\n+\t\topts->edit = -1;\n \t} else if (!file_exists(get_todo_path(opts)))\n \t\treturn continue_single_pick(r, opts);\n \telse if ((res = read_populate_todo(r, &todo_list, opts)))\ndiff --git a/t/t3436-rebase-more-options.sh b/t/t3436-rebase-more-options.sh\nindex 94671d3c46..c84c6717ab 100755\n--- a/t/t3436-rebase-more-options.sh\n+++ b/t/t3436-rebase-more-options.sh\n@@ -201,6 +201,58 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '\n \ttest_atime_is_ignored -2\n '\n \n+test_expect_success '--no-edit on continue uses existing commit message' '\n+\tgit checkout commit2 &&\n+\ttest_must_fail git rebase -m --onto commit2^^ commit2^ &&\n+\techo resolved >foo &&\n+\tgit add foo &&\n+\twrite_script fail-if-editor-invoked <<-\\EOF &&\n+\techo editor invoked >&2\n+\texit 1\n+\tEOF\n+\tGIT_EDITOR=./fail-if-editor-invoked git rebase --continue --no-edit &&\n+\tgit log --format=%s -1 >actual &&\n+\techo commit2 >expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '--no-edit cannot be used when starting a rebase' '\n+\ttest_must_fail git rebase --no-edit -m main side 2>err &&\n+\ttest_grep \"only be used with --continue\" err\n+'\n+\n+test_expect_success 'rebase.noEdit skips editor on continue' '\n+\tgit config rebase.noEdit true &&\n+\tgit checkout commit2 &&\n+\ttest_must_fail git rebase -m --onto commit2^^ commit2^ &&\n+\techo resolved >foo &&\n+\tgit add foo &&\n+\twrite_script fail-if-editor-invoked <<-\\EOF &&\n+\techo editor invoked >&2\n+\texit 1\n+\tEOF\n+\tGIT_EDITOR=./fail-if-editor-invoked git rebase --continue &&\n+\tgit log --format=%s -1 >actual &&\n+\techo commit2 >expect &&\n+\ttest_cmp expect actual\n+'\n+\n+test_expect_success '--edit on continue overrides rebase.noEdit' '\n+\tgit config rebase.noEdit true &&\n+\tgit checkout commit2 &&\n+\ttest_must_fail git rebase -m --onto commit2^^ commit2^ &&\n+\techo resolved >foo &&\n+\tgit add foo &&\n+\t(\n+\t\tset_fake_editor &&\n+\t\tFAKE_COMMIT_MESSAGE=\"edited on continue\" \\\n+\t\t\tgit rebase --continue --edit\n+\t) &&\n+\ttest_write_lines \"edited on continue\" \"\" >expect &&\n+\tgit log --format=%B -1 >actual &&\n+\ttest_cmp expect actual\n+'\n+\n # This must be the last test in this file\n test_expect_success '$EDITOR and friends are unchanged' '\n \ttest_editor_unchanged\n-- \n2.54.0\n\n"},{"id":"548730","messageId":"xmqqldb4xlqa.fsf@gitster.g","threadId":"66045","inReplyTo":"20260721140443.1809379-1-hugo@hsal.es","subject":"Re: [PATCH 0/1] rebase: add --[no-]edit to --continue","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-07-21T18:04:45Z","receivedAt":"2026-07-21T18:04:48Z","isPatch":true,"body":"Hugo Sales <hugo@hsal.es> writes:\n\n> When a rebase stops for conflicts and the user runs `git rebase --continue`, the\n> merge backend opens $EDITOR so the commit message can be revised. That is often\n> useful, but not always: sometimes the user only wants to keep the message that\n> is already there.\n>\n> This series adds:\n>\n> - `git rebase --continue --no-edit` to commit without opening an editor\n\nMeh. \"GIT_SEQUENCE_EDITOR=: git rebase --continue\" is your friend ;-)\n\n> - `rebase.noEdit` to make that the default on continue\n> - `git rebase --continue --edit` to override `rebase.noEdit`\n\nThe new 'rebase.noEdit' configuration is especially concerning.  It\nencourages users to assume by default that their rebase sessions\nwill not produce notable changes worth recording in the commit logs.\n\nA few immediate edge cases come to mind:\n\n - What if 'rebase -i' stops to give control back to the user for\n   reasons other than a merge conflict?  If the user chose 'edit',\n   their original intent was to modify both the commit message and\n   the content.  With 'rebase.noEdit' enabled, would they now have\n   to remember to pass '--edit' when continuing?  Does the answer\n   depend on whether the 'edit' step resulted in a merge conflict?\n\n - What if the user chose 'reword', which is an explicit signal to\n   update the commit message, but 'rebase.noEdit' is enabled?  If\n   the rebase does not stop with a conflict, it might open the\n   editor regardless of the configuration.  But if a conflict does\n   occur and requires manual resolution, will the user still need to\n   remember to pass '--edit' when continuing?\n\nThe proposed tests only cover the code path where control returns to\nthe user due to a conflict.  This is understandable since that\nscenario was your primary motivation.  However, they do not verify\nwhat happens when there are no conflicts but the user explicitly\nintended to edit the message from the start.  You may want to expand\nthe test coverage to address these scenarios (and potentially\nothers, as this is not an exhaustive list).\n\nThanks.\n"},{"id":"548778","messageId":"db7edc66-9b2a-47bc-98db-87d01885cef0@gmail.com","threadId":"66045","inReplyTo":"xmqqldb4xlqa.fsf@gitster.g","subject":"Re: [PATCH 0/1] rebase: add --[no-]edit to --continue","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2026-07-22T13:39:32Z","receivedAt":"2026-07-22T13:39:39Z","isPatch":true,"body":"On 21/07/2026 19:04, Junio C Hamano wrote:\n> Hugo Sales <hugo@hsal.es> writes:\n> \n>> When a rebase stops for conflicts and the user runs `git rebase --continue`, the\n>> merge backend opens $EDITOR so the commit message can be revised. That is often\n>> useful, but not always: sometimes the user only wants to keep the message that\n>> is already there.\n>>\n>> This series adds:\n>>\n>> - `git rebase --continue --no-edit` to commit without opening an editor\n> \n> Meh. \"GIT_SEQUENCE_EDITOR=: git rebase --continue\" is your friend ;-)\n\nDo you mean \"GIT_EDITOR=:\"? The sequence editor is only relevant for \nediting the todo list. The last time this came up [1] I shared an alias \nthat only suppresses the editor if HEAD has not changed since the user \ncontinued the rebase, but that does not stop the user suppressing the \neditor when continuing a \"reword\" command. I share the concerns you \nlisted below about this patch in its current form.\n\nThanks\n\nPhillip\n\n[1] \nhttps://lore.kernel.org/git/fbf859ca-43f4-433e-b111-377aa60f1947@gmail.com\n\n>> - `rebase.noEdit` to make that the default on continue\n>> - `git rebase --continue --edit` to override `rebase.noEdit`\n> \n> The new 'rebase.noEdit' configuration is especially concerning.  It\n> encourages users to assume by default that their rebase sessions\n> will not produce notable changes worth recording in the commit logs.\n> \n> A few immediate edge cases come to mind:\n> \n>   - What if 'rebase -i' stops to give control back to the user for\n>     reasons other than a merge conflict?  If the user chose 'edit',\n>     their original intent was to modify both the commit message and\n>     the content.  With 'rebase.noEdit' enabled, would they now have\n>     to remember to pass '--edit' when continuing?  Does the answer\n>     depend on whether the 'edit' step resulted in a merge conflict?\n> \n>   - What if the user chose 'reword', which is an explicit signal to\n>     update the commit message, but 'rebase.noEdit' is enabled?  If\n>     the rebase does not stop with a conflict, it might open the\n>     editor regardless of the configuration.  But if a conflict does\n>     occur and requires manual resolution, will the user still need to\n>     remember to pass '--edit' when continuing?\n> \n> The proposed tests only cover the code path where control returns to\n> the user due to a conflict.  This is understandable since that\n> scenario was your primary motivation.  However, they do not verify\n> what happens when there are no conflicts but the user explicitly\n> intended to edit the message from the start.  You may want to expand\n> the test coverage to address these scenarios (and potentially\n> others, as this is not an exhaustive list).\n> \n> Thanks.\n> \n\n"},{"id":"548784","messageId":"xmqqse5brq8s.fsf@gitster.g","threadId":"66045","inReplyTo":"db7edc66-9b2a-47bc-98db-87d01885cef0@gmail.com","subject":"Re: [PATCH 0/1] rebase: add --[no-]edit to --continue","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-07-22T15:36:03Z","receivedAt":"2026-07-22T15:36:06Z","isPatch":true,"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> On 21/07/2026 19:04, Junio C Hamano wrote:\n>> Hugo Sales <hugo@hsal.es> writes:\n>> \n>>> When a rebase stops for conflicts and the user runs `git rebase --continue`, the\n>>> merge backend opens $EDITOR so the commit message can be revised. That is often\n>>> useful, but not always: sometimes the user only wants to keep the message that\n>>> is already there.\n>>>\n>>> This series adds:\n>>>\n>>> - `git rebase --continue --no-edit` to commit without opening an editor\n>> \n>> Meh. \"GIT_SEQUENCE_EDITOR=: git rebase --continue\" is your friend ;-)\n>\n> Do you mean \"GIT_EDITOR=:\"? The sequence editor is only relevant for \n\nOh, absolutely.  I made a last minute change s/_EDITOR/SEQUENCE_&/\nbefore sending it out, without realizing that I made a totally\nunnecessary change X-<.\n\nThanks for spotting.\n\n> editing the todo list.\n\n"}]}