git pull --rebase leads to unexpected graph

自古美人都是妖i 提交于 2019-12-22 12:36:06

问题


I am working on a branch, foo. I have no unstaged changes, no working changes, perfectly clean state, where HEAD == foo == origin/foo according to my box.

$ git status
# On branch foo
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   some_irrelevant_file_here

$ git log --pretty=...
* 456520c 2015-02-13 (HEAD, origin/foo, foo) Commit A
* 23bfcd1 2015-02-11 Commit B
* b0bdd18 2015-02-12 Commit C

I am then asked to look at some changes that a colleague pushed, so I do:

$ git pull --rebase origin foo
remote: Counting objects: 47, done.
remote: Compressing objects: 100% (34/34), done.
remote: Total 36 (delta 22), reused 0 (delta 0)
Unpacking objects: 100% (36/36), done.
From ...
 * branch            foo       -> FETCH_HEAD
First, rewinding head to replay your work on top of it...
Fast-forwarded foo to 43dad88c737762e0f1e84fdcd135155080bdce2a.

At this point, my graph looks like:

$ git log --pretty=...
* 43dad88 2015-02-13 (HEAD, foo) Commit D
* 40039f9 2015-02-13 Commit E
* 456520c 2015-02-13 (origin/foo) Commit A
* 23bfcd1 2015-02-11 Commit B
* b0bdd18 2015-02-12 Commit C

Why does it look like my local foo is ahead of origin/foo? Neither D nor E are my commits, I just pulled both of those from origin - I'd expect at this point to still have HEAD == foo == origin/foo.


回答1:


What you had before the pull --rebase was:

x--x--x (foo, HEAD, origin/foo)
       \
        y--y (actual origin/foo)

When you pull --rebase, you are asking to replay your local commits on top of origin/foo:
foo is reset/checked out at origin/foo (which is fetched in FETCH_HEAD), and since your commits 'x' are already part of the new updated FETCH_HEAD, foo is simply fast-forwarded:

x--x--x--y--y (foo, HEAD, FETCH_HEAD)
      |
 (origin/foo)

The fact that origin/foo has not changed is typical of a git older than 1.8.4 (found for instance in Ubuntu Precise 12.04, which comes with and old git-core 1.7.9.5)

A simple git fetch should be enough to update origin/foo, and not just FETCH_HEAD.

A more recent git (1.8.4+) would have updated both FETCH_HEAD and origin/foo, making the additional git fetch redundant.


Note: with Git 2.12 (Q1 2017), this case (pull --rebase) will be a simple fast-forward merge.

See commit 33b842a (29 Jun 2016) by Junio C Hamano (gitster). (Merged by Junio C Hamano -- gitster -- in commit 2fb11ec, 19 Dec 2016)

pull: fast-forward "pull --rebase=true"

"git pull --rebase" always runs "git rebase" after fetching the commit to serve as the new base, even when the new base is a descendant of the current HEAD, i.e. we haven't done any work.

In such a case, we can instead fast-forward to the new base without invoking the rebase process.




回答2:


Since it is not pushed to the repo that is a normal behavior. How come you can have your local commits before origin? They will always be on top.




回答3:


Why does it look like my local foo is ahead of origin/foo?

That foo is ahead of remote/foo is expected, because rebase plays back your current branch on top of the upstream branch. You rebased foo on top of the remote/foo, so foo should be ahead of remote/foo.

HEAD == foo == origin/foo according to my box.

As a result, the order of commits is also as expected. The following is how your branching would look before a rebase or merge where A is the actual state of the remote and C is your stale representation of the remote.

D <------C (HEAD, foo, remote/foo) <------B <------A (remote/foo)

You're doing the equivalent of a "fast-forward" rebase. I.e. it doesn't do anything to the commits; there is nothing to play back onto remote/foo! The result should only change ref locations:

D <------C <------B <------A (HEAD, foo, remote/foo)

Why does it look like my local foo is ahead of origin/foo?

That's the question I haven't been able to answer. After the rebase, I would expect again that HEAD == foo == remote/foo but it doesn't. Why after the rebase of foo onto remote/foo does the latter appear to be behind?



来源:https://stackoverflow.com/questions/28502116/git-pull-rebase-leads-to-unexpected-graph

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!