OSDN Git Service

Merge branch 'jc/pull-rebase-ff' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 17 Jan 2017 23:11:04 +0000 (15:11 -0800)
committerJunio C Hamano <gitster@pobox.com>
Tue, 17 Jan 2017 23:11:05 +0000 (15:11 -0800)
"git pull --rebase", when there is no new commits on our side since
we forked from the upstream, should be able to fast-forward without
invoking "git rebase", but it didn't.

* jc/pull-rebase-ff:
  pull: fast-forward "pull --rebase=true"

builtin/pull.c
t/t5520-pull.sh

index d6e46ee..3ecb881 100644 (file)
@@ -857,10 +857,24 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
                if (merge_heads.nr > 1)
                        die(_("Cannot merge multiple branches into empty head."));
                return pull_into_void(*merge_heads.sha1, curr_head);
-       } else if (opt_rebase) {
-               if (merge_heads.nr > 1)
-                       die(_("Cannot rebase onto multiple branches."));
+       }
+       if (opt_rebase && merge_heads.nr > 1)
+               die(_("Cannot rebase onto multiple branches."));
+
+       if (opt_rebase) {
+               struct commit_list *list = NULL;
+               struct commit *merge_head, *head;
+
+               head = lookup_commit_reference(orig_head);
+               commit_list_insert(head, &list);
+               merge_head = lookup_commit_reference(merge_heads.sha1[0]);
+               if (is_descendant_of(merge_head, list)) {
+                       /* we can fast-forward this without invoking rebase */
+                       opt_ff = "--ff-only";
+                       return run_merge();
+               }
                return run_rebase(curr_head, *merge_heads.sha1, rebase_fork_point);
-       } else
+       } else {
                return run_merge();
+       }
 }
index 5518445..17f4d0f 100755 (executable)
@@ -255,6 +255,23 @@ test_expect_success '--rebase' '
        test new = "$(git show HEAD:file2)"
 '
 
+test_expect_success '--rebase fast forward' '
+       git reset --hard before-rebase &&
+       git checkout -b ff &&
+       echo another modification >file &&
+       git commit -m third file &&
+
+       git checkout to-rebase &&
+       git pull --rebase . ff &&
+       test "$(git rev-parse HEAD)" = "$(git rev-parse ff)" &&
+
+       # The above only validates the result.  Did we actually bypass rebase?
+       git reflog -1 >reflog.actual &&
+       sed "s/^[0-9a-f][0-9a-f]*/OBJID/" reflog.actual >reflog.fuzzy &&
+       echo "OBJID HEAD@{0}: pull --rebase . ff: Fast-forward" >reflog.expected &&
+       test_cmp reflog.expected reflog.fuzzy
+'
+
 test_expect_success '--rebase with conflicts shows advice' '
        test_when_finished "git rebase --abort; git checkout -f to-rebase" &&
        git checkout -b seq &&