Merge branch 'hs/rebase-continue-edit' into seen
Support for skipping the editor when continuing a rebase after conflict resolution has been added with the '--no-edit' option, and forcing it with '--edit'. A new configuration variable 'rebase.noEdit' can be used to set the default behavior. * hs/rebase-continue-edit: rebase: add --[no-]edit to --continueseen
commit
b739b27211
|
|
@ -62,6 +62,12 @@ instead of:
|
||||||
+
|
+
|
||||||
Defaults to false.
|
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::
|
rebase.rescheduleFailedExec::
|
||||||
Automatically reschedule `exec` commands that failed. This only makes
|
Automatically reschedule `exec` commands that failed. This only makes
|
||||||
sense in interactive mode (or when an `--exec` option was provided).
|
sense in interactive mode (or when an `--exec` option was provided).
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,16 @@ including not with each other:
|
||||||
|
|
||||||
--continue::
|
--continue::
|
||||||
Restart the rebasing process after having resolved a merge conflict.
|
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::
|
--skip::
|
||||||
Restart the rebasing process by skipping the current patch.
|
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
|
When a conflict occurs while rebasing, rebase stops and asks the user
|
||||||
to resolve. Since the user may need to make notable changes while
|
to resolve. Since the user may need to make notable changes while
|
||||||
resolving conflicts, after conflicts are resolved and the user has run
|
resolving conflicts, after conflicts are resolved and the user has run
|
||||||
`git rebase --continue`, the rebase should open an editor and ask the
|
`git rebase --continue`, the rebase opens an editor and asks the
|
||||||
user to update the commit message. The 'merge' backend does this, while
|
user to update the commit message, unless `rebase.noEdit` is set or
|
||||||
the 'apply' backend blindly applies the original commit message.
|
`--no-edit` is passed to `--continue`. The 'merge' backend does this,
|
||||||
|
while the 'apply' backend blindly applies the original commit message.
|
||||||
|
|
||||||
Miscellaneous differences
|
Miscellaneous differences
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ static char const * const builtin_rebase_usage[] = {
|
||||||
"[--onto <newbase> | --keep-base] [<upstream> [<branch>]]"),
|
"[--onto <newbase> | --keep-base] [<upstream> [<branch>]]"),
|
||||||
N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
|
N_("git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] "
|
||||||
"--root [<branch>]"),
|
"--root [<branch>]"),
|
||||||
"git rebase --continue | --abort | --skip | --edit-todo",
|
"git rebase --continue [--[no-]edit] | --abort | --skip | --edit-todo",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -135,6 +135,8 @@ struct rebase_options {
|
||||||
int config_autosquash;
|
int config_autosquash;
|
||||||
int config_rebase_merges;
|
int config_rebase_merges;
|
||||||
int config_update_refs;
|
int config_update_refs;
|
||||||
|
int config_no_edit;
|
||||||
|
int edit;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define REBASE_OPTIONS_INIT { \
|
#define REBASE_OPTIONS_INIT { \
|
||||||
|
|
@ -156,6 +158,8 @@ struct rebase_options {
|
||||||
.update_refs = -1, \
|
.update_refs = -1, \
|
||||||
.config_update_refs = -1, \
|
.config_update_refs = -1, \
|
||||||
.strategy_opts = STRING_LIST_INIT_NODUP,\
|
.strategy_opts = STRING_LIST_INIT_NODUP,\
|
||||||
|
.config_no_edit = -1, \
|
||||||
|
.edit = -1, \
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rebase_options_release(struct rebase_options *opts)
|
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;
|
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;
|
return replay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -841,6 +852,11 @@ static int rebase_config(const char *var, const char *value,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(var, "rebase.noedit")) {
|
||||||
|
opts->config_no_edit = git_config_bool(var, value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!strcmp(var, "rebase.forkpoint")) {
|
if (!strcmp(var, "rebase.forkpoint")) {
|
||||||
opts->fork_point = git_config_bool(var, value) ? -1 : 0;
|
opts->fork_point = git_config_bool(var, value) ? -1 : 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1171,6 +1187,8 @@ int cmd_rebase(int argc,
|
||||||
ACTION_CONTINUE),
|
ACTION_CONTINUE),
|
||||||
OPT_CMDMODE(0, "skip", &options.action,
|
OPT_CMDMODE(0, "skip", &options.action,
|
||||||
N_("skip current patch and continue"), ACTION_SKIP),
|
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,
|
OPT_CMDMODE(0, "abort", &options.action,
|
||||||
N_("abort and check out the original branch"),
|
N_("abort and check out the original branch"),
|
||||||
ACTION_ABORT),
|
ACTION_ABORT),
|
||||||
|
|
@ -1311,10 +1329,15 @@ int cmd_rebase(int argc,
|
||||||
"which is no longer supported; use 'merges' instead"));
|
"which is no longer supported; use 'merges' instead"));
|
||||||
|
|
||||||
if (options.action != ACTION_NONE && total_argc != 2) {
|
if (options.action != ACTION_NONE && total_argc != 2) {
|
||||||
usage_with_options(builtin_rebase_usage,
|
if (options.action != ACTION_CONTINUE ||
|
||||||
builtin_rebase_options);
|
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)
|
if (argc > 2)
|
||||||
usage_with_options(builtin_rebase_usage,
|
usage_with_options(builtin_rebase_usage,
|
||||||
builtin_rebase_options);
|
builtin_rebase_options);
|
||||||
|
|
|
||||||
29
sequencer.c
29
sequencer.c
|
|
@ -2231,6 +2231,25 @@ static int should_edit(struct replay_opts *opts) {
|
||||||
return opts->edit;
|
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,
|
static void refer_to_commit(struct repository *r, struct strbuf *msgbuf,
|
||||||
const struct commit *commit,
|
const struct commit *commit,
|
||||||
bool use_commit_reference)
|
bool use_commit_reference)
|
||||||
|
|
@ -5360,7 +5379,7 @@ static int commit_staged_changes(struct repository *r,
|
||||||
struct todo_list *todo_list)
|
struct todo_list *todo_list)
|
||||||
{
|
{
|
||||||
struct replay_ctx *ctx = opts->ctx;
|
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;
|
unsigned int final_fixup = 0, is_clean;
|
||||||
struct strbuf rev = STRBUF_INIT;
|
struct strbuf rev = STRBUF_INIT;
|
||||||
const char *reflog_action = reflog_message(opts, "continue", NULL);
|
const char *reflog_action = reflog_message(opts, "continue", NULL);
|
||||||
|
|
@ -5528,6 +5547,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(),
|
if (run_git_commit(final_fixup ? NULL : rebase_path_message(),
|
||||||
reflog_action, opts, flags)) {
|
reflog_action, opts, flags)) {
|
||||||
ret = error(_("could not commit staged changes."));
|
ret = error(_("could not commit staged changes."));
|
||||||
|
|
@ -5585,6 +5606,12 @@ int sequencer_continue(struct repository *r, struct replay_opts *opts)
|
||||||
res = -1;
|
res = -1;
|
||||||
goto release_todo_list;
|
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)))
|
} else if (!file_exists(get_todo_path(opts)))
|
||||||
return continue_single_pick(r, opts);
|
return continue_single_pick(r, opts);
|
||||||
else if ((res = read_populate_todo(r, &todo_list, opts)))
|
else if ((res = read_populate_todo(r, &todo_list, opts)))
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,58 @@ test_expect_success '--ignore-date is an alias for --reset-author-date' '
|
||||||
test_atime_is_ignored -2
|
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
|
# This must be the last test in this file
|
||||||
test_expect_success '$EDITOR and friends are unchanged' '
|
test_expect_success '$EDITOR and friends are unchanged' '
|
||||||
test_editor_unchanged
|
test_editor_unchanged
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue