sequencer: fast-forward merge commits, if possible
[gitweb.git] / sequencer.c
index ec48c965be34410796f8a0f113f8c885a1a1a1b5..173949602e444b41478de66c71d84550b42bc3f2 100644 (file)
@@ -2129,7 +2129,7 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
        struct commit *head_commit, *merge_commit, *i;
        struct commit_list *common, *j, *reversed = NULL;
        struct merge_options o;
-       int ret;
+       int can_fast_forward, ret;
        static struct lock_file lock;
 
        for (merge_arg_len = 0; merge_arg_len < arg_len; merge_arg_len++)
@@ -2197,6 +2197,14 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
                strbuf_release(&buf);
        }
 
+       /*
+        * If HEAD is not identical to the parent of the original merge commit,
+        * we cannot fast-forward.
+        */
+       can_fast_forward = opts->allow_ff && commit && commit->parents &&
+               !oidcmp(&commit->parents->item->object.oid,
+                       &head_commit->object.oid);
+
        strbuf_addf(&ref_name, "refs/rewritten/%.*s", merge_arg_len, arg);
        merge_commit = lookup_commit_reference_by_name(ref_name.buf);
        if (!merge_commit) {
@@ -2210,6 +2218,17 @@ static int do_merge(struct commit *commit, const char *arg, int arg_len,
                rollback_lock_file(&lock);
                return -1;
        }
+
+       if (can_fast_forward && commit->parents->next &&
+           !commit->parents->next->next &&
+           !oidcmp(&commit->parents->next->item->object.oid,
+                   &merge_commit->object.oid)) {
+               strbuf_release(&ref_name);
+               rollback_lock_file(&lock);
+               return fast_forward_to(&commit->object.oid,
+                                      &head_commit->object.oid, 0, opts);
+       }
+
        write_message(oid_to_hex(&merge_commit->object.oid), GIT_SHA1_HEXSZ,
                      git_path_merge_head(), 0);
        write_message("no-ff", 5, git_path_merge_mode(), 0);