path: root/builtin
diff options
authorElijah Newren <>2020-02-15 21:36:31 (GMT)
committerJunio C Hamano <>2020-02-16 23:40:42 (GMT)
commitbefb89ce7c43a0bd0de11909951dd3015874e9db (patch)
tree06cdb3a48fa78ec38964e9321d1f5fd08c9a9f83 /builtin
parent9a70f3d4ae673e02e78b1061fcc8fc01bc8d9276 (diff)
rebase: allow more types of rebases to fast-forward
In the past, we dis-allowed rebases using the interactive backend from performing a fast-forward to short-circuit the rebase operation. This made sense for explicitly interactive rebases and some implicitly interactive rebases, but certainly became overly stringent when the merge backend was re-implemented via the interactive backend. Just as the am-based rebase has always had to disable the fast-forward based on a variety of conditions or flags (e.g. --signoff, --whitespace, etc.), we need to do the same but now with a few more options. However, continuing to use REBASE_FORCE for tracking this is problematic because the interactive backend used it for a different purpose. (When REBASE_FORCE wasn't set, the interactive backend would not fast-forward the whole series but would fast-forward individual "pick" commits at the beginning of the todo list, and then a squash or something would cause it to start generating new commits.) So, introduce a new allow_preemptive_ff flag contained within cmd_rebase() and use it to track whether we are going to allow a pre-emptive fast-forward that short-circuits the whole rebase. Signed-off-by: Elijah Newren <> Signed-off-by: Junio C Hamano <>
Diffstat (limited to 'builtin')
1 files changed, 14 insertions, 4 deletions
diff --git a/builtin/rebase.c b/builtin/rebase.c
index 8264a92..6e9a2fe 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -1467,6 +1467,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
struct object_id squash_onto;
char *squash_onto_name = NULL;
int reschedule_failed_exec = -1;
+ int allow_preemptive_ff = 1;
struct option builtin_rebase_options[] = {
OPT_STRING(0, "onto", &options.onto_name,
@@ -1774,13 +1775,20 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
state_dir_base, cmd_live_rebase, buf.buf);
+ if ((options.flags & REBASE_INTERACTIVE_EXPLICIT) ||
+ (action != ACTION_NONE) ||
+ ( > 0) ||
+ options.autosquash) {
+ allow_preemptive_ff = 0;
+ }
for (i = 0; i < options.git_am_opts.argc; i++) {
const char *option = options.git_am_opts.argv[i], *p;
if (!strcmp(option, "--committer-date-is-author-date") ||
!strcmp(option, "--ignore-date") ||
!strcmp(option, "--whitespace=fix") ||
!strcmp(option, "--whitespace=strip"))
- options.flags |= REBASE_FORCE;
+ allow_preemptive_ff = 0;
else if (skip_prefix(option, "-C", &p)) {
while (*p)
if (!isdigit(*(p++)))
@@ -2116,12 +2124,14 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)
* Check if we are already based on onto with linear history,
* in which case we could fast-forward without replacing the commits
- * with new commits recreated by replaying their changes. This
- * optimization must not be done if this is an interactive rebase.
+ * with new commits recreated by replaying their changes.
+ *
+ * Note that can_fast_forward() initializes merge_base, so we have to
+ * call it before checking allow_preemptive_ff.
if (can_fast_forward(options.onto, options.upstream, options.restrict_revision,
&options.orig_head, &merge_base) &&
- !is_interactive(&options)) {
+ allow_preemptive_ff) {
int flag;
if (!(options.flags & REBASE_FORCE)) {