Skip to content

Commit 179eccf

Browse files
someonewithpcgitster
authored andcommitted
rebase: add --[no-]edit to --continue
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> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent e9019fc commit 179eccf

5 files changed

Lines changed: 126 additions & 7 deletions

File tree

Documentation/config/rebase.adoc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ instead of:
6262
+
6363
Defaults to false.
6464
65+
rebase.noEdit::
66+
When set to true, `git rebase --continue` uses the commit message
67+
without launching $EDITOR, as if `--no-edit` were given. The
68+
`--edit` option to `git rebase --continue` overrides this setting.
69+
Defaults to false.
70+
6571
rebase.rescheduleFailedExec::
6672
Automatically reschedule `exec` commands that failed. This only makes
6773
sense in interactive mode (or when an `--exec` option was provided).

Documentation/git-rebase.adoc

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,16 @@ including not with each other:
181181
182182
--continue::
183183
Restart the rebasing process after having resolved a merge conflict.
184+
+
185+
-e::
186+
--edit::
187+
--no-edit::
188+
With `--continue`, edit or do not edit the commit message,
189+
respectively. By default, the configured $EDITOR is opened so you
190+
can update the commit message after resolving conflicts.
191+
`--no-edit` reuses the existing message without launching an
192+
editor. The `rebase.noEdit` configuration variable can be used to
193+
enable `--no-edit` by default; `--edit` overrides that setting.
184194
185195
--skip::
186196
Restart the rebasing process by skipping the current patch.
@@ -783,9 +793,10 @@ Commit Rewording
783793
When a conflict occurs while rebasing, rebase stops and asks the user
784794
to resolve. Since the user may need to make notable changes while
785795
resolving conflicts, after conflicts are resolved and the user has run
786-
`git rebase --continue`, the rebase should open an editor and ask the
787-
user to update the commit message. The 'merge' backend does this, while
788-
the 'apply' backend blindly applies the original commit message.
796+
`git rebase --continue`, the rebase opens an editor and asks the
797+
user to update the commit message, unless `rebase.noEdit` is set or
798+
`--no-edit` is passed to `--continue`. The 'merge' backend does this,
799+
while the 'apply' backend blindly applies the original commit message.
789800

790801
Miscellaneous differences
791802
~~~~~~~~~~~~~~~~~~~~~~~~~

builtin/rebase.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ static char const * const builtin_rebase_usage[] = {
4343
"[--onto <newbase> | --keep-base] [<upstream> [<branch>]]"),
4444
N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
4545
"--root [<branch>]"),
46-
"git rebase --continue | --abort | --skip | --edit-todo",
46+
"git rebase --continue [--[no-]edit] | --abort | --skip | --edit-todo",
4747
NULL
4848
};
4949

@@ -135,6 +135,8 @@ struct rebase_options {
135135
int config_autosquash;
136136
int config_rebase_merges;
137137
int config_update_refs;
138+
int config_no_edit;
139+
int edit;
138140
};
139141

140142
#define REBASE_OPTIONS_INIT { \
@@ -156,6 +158,8 @@ struct rebase_options {
156158
.update_refs = -1, \
157159
.config_update_refs = -1, \
158160
.strategy_opts = STRING_LIST_INIT_NODUP,\
161+
.config_no_edit = -1, \
162+
.edit = -1, \
159163
}
160164

161165
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)
215219
replay.have_squash_onto = 1;
216220
}
217221

222+
if (opts->action == ACTION_CONTINUE) {
223+
if (opts->edit >= 0)
224+
replay.edit = opts->edit;
225+
else if (opts->config_no_edit > 0)
226+
replay.edit = 0;
227+
}
228+
218229
return replay;
219230
}
220231

@@ -839,6 +850,11 @@ static int rebase_config(const char *var, const char *value,
839850
return 0;
840851
}
841852

853+
if (!strcmp(var, "rebase.noedit")) {
854+
opts->config_no_edit = git_config_bool(var, value);
855+
return 0;
856+
}
857+
842858
if (!strcmp(var, "rebase.forkpoint")) {
843859
opts->fork_point = git_config_bool(var, value) ? -1 : 0;
844860
return 0;
@@ -1168,6 +1184,8 @@ int cmd_rebase(int argc,
11681184
ACTION_CONTINUE),
11691185
OPT_CMDMODE(0, "skip", &options.action,
11701186
N_("skip current patch and continue"), ACTION_SKIP),
1187+
OPT_BOOL('e', "edit", &options.edit,
1188+
N_("edit the commit message")),
11711189
OPT_CMDMODE(0, "abort", &options.action,
11721190
N_("abort and check out the original branch"),
11731191
ACTION_ABORT),
@@ -1308,10 +1326,15 @@ int cmd_rebase(int argc,
13081326
"which is no longer supported; use 'merges' instead"));
13091327

13101328
if (options.action != ACTION_NONE && total_argc != 2) {
1311-
usage_with_options(builtin_rebase_usage,
1312-
builtin_rebase_options);
1329+
if (options.action != ACTION_CONTINUE ||
1330+
options.edit < 0 || total_argc != 3)
1331+
usage_with_options(builtin_rebase_usage,
1332+
builtin_rebase_options);
13131333
}
13141334

1335+
if (options.edit >= 0 && options.action != ACTION_CONTINUE)
1336+
die(_("--edit and --no-edit can only be used with --continue"));
1337+
13151338
if (argc > 2)
13161339
usage_with_options(builtin_rebase_usage,
13171340
builtin_rebase_options);

sequencer.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2211,6 +2211,25 @@ static int should_edit(struct replay_opts *opts) {
22112211
return opts->edit;
22122212
}
22132213

2214+
static int should_edit_rebase_continue(struct replay_opts *opts)
2215+
{
2216+
if (opts->edit < 0)
2217+
return 1;
2218+
return opts->edit;
2219+
}
2220+
2221+
static void finalize_continue_edit_flags(struct replay_opts *opts,
2222+
unsigned int *flags)
2223+
{
2224+
if (*flags & CLEANUP_MSG)
2225+
return;
2226+
2227+
if (should_edit_rebase_continue(opts))
2228+
*flags |= EDIT_MSG;
2229+
else
2230+
*flags &= ~EDIT_MSG;
2231+
}
2232+
22142233
static void refer_to_commit(struct repository *r, struct strbuf *msgbuf,
22152234
const struct commit *commit,
22162235
bool use_commit_reference)
@@ -5261,7 +5280,7 @@ static int commit_staged_changes(struct repository *r,
52615280
struct todo_list *todo_list)
52625281
{
52635282
struct replay_ctx *ctx = opts->ctx;
5264-
unsigned int flags = ALLOW_EMPTY | EDIT_MSG;
5283+
unsigned int flags = ALLOW_EMPTY;
52655284
unsigned int final_fixup = 0, is_clean;
52665285
struct strbuf rev = STRBUF_INIT;
52675286
const char *reflog_action = reflog_message(opts, "continue", NULL);
@@ -5426,6 +5445,8 @@ static int commit_staged_changes(struct repository *r,
54265445
}
54275446
}
54285447

5448+
finalize_continue_edit_flags(opts, &flags);
5449+
54295450
if (run_git_commit(final_fixup ? NULL : rebase_path_message(),
54305451
reflog_action, opts, flags)) {
54315452
ret = error(_("could not commit staged changes."));
@@ -5483,6 +5504,12 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts)
54835504
res = -1;
54845505
goto release_todo_list;
54855506
}
5507+
5508+
/*
5509+
* Command-line --[no-]edit applies only to this
5510+
* --continue invocation, not to subsequent picks.
5511+
*/
5512+
opts->edit = -1;
54865513
} else if (!file_exists(get_todo_path(opts)))
54875514
return continue_single_pick(r, opts);
54885515
else if ((res = read_populate_todo(r, &todo_list, opts)))

t/t3436-rebase-more-options.sh

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,58 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '
201201
test_atime_is_ignored -2
202202
'
203203

204+
test_expect_success '--no-edit on continue uses existing commit message' '
205+
git checkout commit2 &&
206+
test_must_fail git rebase -m --onto commit2^^ commit2^ &&
207+
echo resolved >foo &&
208+
git add foo &&
209+
write_script fail-if-editor-invoked <<-\EOF &&
210+
echo editor invoked >&2
211+
exit 1
212+
EOF
213+
GIT_EDITOR=./fail-if-editor-invoked git rebase --continue --no-edit &&
214+
git log --format=%s -1 >actual &&
215+
echo commit2 >expect &&
216+
test_cmp expect actual
217+
'
218+
219+
test_expect_success '--no-edit cannot be used when starting a rebase' '
220+
test_must_fail git rebase --no-edit -m main side 2>err &&
221+
test_grep "only be used with --continue" err
222+
'
223+
224+
test_expect_success 'rebase.noEdit skips editor on continue' '
225+
git config rebase.noEdit true &&
226+
git checkout commit2 &&
227+
test_must_fail git rebase -m --onto commit2^^ commit2^ &&
228+
echo resolved >foo &&
229+
git add foo &&
230+
write_script fail-if-editor-invoked <<-\EOF &&
231+
echo editor invoked >&2
232+
exit 1
233+
EOF
234+
GIT_EDITOR=./fail-if-editor-invoked git rebase --continue &&
235+
git log --format=%s -1 >actual &&
236+
echo commit2 >expect &&
237+
test_cmp expect actual
238+
'
239+
240+
test_expect_success '--edit on continue overrides rebase.noEdit' '
241+
git config rebase.noEdit true &&
242+
git checkout commit2 &&
243+
test_must_fail git rebase -m --onto commit2^^ commit2^ &&
244+
echo resolved >foo &&
245+
git add foo &&
246+
(
247+
set_fake_editor &&
248+
FAKE_COMMIT_MESSAGE="edited on continue" \
249+
git rebase --continue --edit
250+
) &&
251+
test_write_lines "edited on continue" "" >expect &&
252+
git log --format=%B -1 >actual &&
253+
test_cmp expect actual
254+
'
255+
204256
# This must be the last test in this file
205257
test_expect_success '$EDITOR and friends are unchanged' '
206258
test_editor_unchanged

0 commit comments

Comments
 (0)