git pull --rebase 导致意外的图表
git pull --rebase leads to unexpected graph
我在分支机构工作,foo
。我没有未暂存的更改,没有工作更改,完全干净的状态,其中 HEAD
== foo
== origin/foo
根据我的框。
$ 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
然后我被要求查看同事推送的一些更改,所以我做了:
$ 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.
此时,我的图表如下所示:
$ 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
为什么我的本地 foo
看起来比 origin/foo
领先? D
和 E
都不是我的提交,我只是从 origin
中提取了这两个 - 我希望此时仍然有 HEAD
== foo
== origin/foo
.
因为它没有被推送到 repo,这是一种正常行为。为什么你可以在 origin 之前进行本地提交?他们永远在最前面。
Why does it look like my local foo is ahead of origin/foo?
foo
领先于 remote/foo
是意料之中的,因为 rebase plays back your current branch on top of the upstream branch。您将 foo
重新定位在 remote/foo
之上,因此 foo
应该领先于 remote/foo
。
HEAD == foo == origin/foo according to my box.
因此,提交的顺序也符合预期。以下是 在 变基或合并之前分支的外观,其中 A
是远程的实际状态,C
是远程的陈旧表示。
D <------C (HEAD, foo, remote/foo) <------B <------A (remote/foo)
您所做的相当于 "fast-forward" 变基。 IE。它对提交没有任何作用; remote/foo
上没有什么可播放的!结果应该只改变参考位置:
D <------C <------B <------A (HEAD, foo, remote/foo)
Why does it look like my local foo is ahead of origin/foo?
这是我无法回答的问题。在变基之后,我会再次期望 HEAD
== foo
== remote/foo
但事实并非如此。为什么在 foo
变基到 remote/foo
之后后者似乎落后了?
您在 pull --rebase
之前拥有的是:
x--x--x (foo, HEAD, origin/foo)
\
y--y (actual origin/foo)
当您 pull --rebase
时,您要求在 origin/foo
之上重播您的本地提交:
foo
在 origin/foo
处 reset/checked(在 FETCH_HEAD
中获取),并且由于您的提交 'x
' 已经是新更新 FETCH_HEAD
, foo
只是快进:
x--x--x--y--y (foo, HEAD, FETCH_HEAD)
|
(origin/foo)
origin/foo
未 更改的事实是 git older than 1.8.4 (found for instance in Ubuntu Precise 12.04 的典型特征,它与旧的 git-core
1.7.9.5 一起提供)
一个简单的 git fetch
应该足以更新 origin/foo
,而不仅仅是 FETCH_HEAD
.
较新的 git (1.8.4+) 会同时更新 FETCH_HEAD
和 origin/foo
,从而使额外的 git fetch
变得多余。
注意:对于 Git 2.12(2017 年第一季度),这种情况 (pull --rebase) 将是一个简单的快进合并。
参见 commit 33b842a (29 Jun 2016) by Junio C Hamano (gitster
)。
(由 Junio C Hamano -- gitster
-- in commit 2fb11ec 合并,2016 年 12 月 19 日)
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.
我在分支机构工作,foo
。我没有未暂存的更改,没有工作更改,完全干净的状态,其中 HEAD
== foo
== origin/foo
根据我的框。
$ 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
然后我被要求查看同事推送的一些更改,所以我做了:
$ 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.
此时,我的图表如下所示:
$ 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
为什么我的本地 foo
看起来比 origin/foo
领先? D
和 E
都不是我的提交,我只是从 origin
中提取了这两个 - 我希望此时仍然有 HEAD
== foo
== origin/foo
.
因为它没有被推送到 repo,这是一种正常行为。为什么你可以在 origin 之前进行本地提交?他们永远在最前面。
Why does it look like my local foo is ahead of origin/foo?
foo
领先于 remote/foo
是意料之中的,因为 rebase plays back your current branch on top of the upstream branch。您将 foo
重新定位在 remote/foo
之上,因此 foo
应该领先于 remote/foo
。
HEAD == foo == origin/foo according to my box.
因此,提交的顺序也符合预期。以下是 在 变基或合并之前分支的外观,其中 A
是远程的实际状态,C
是远程的陈旧表示。
D <------C (HEAD, foo, remote/foo) <------B <------A (remote/foo)
您所做的相当于 "fast-forward" 变基。 IE。它对提交没有任何作用; remote/foo
上没有什么可播放的!结果应该只改变参考位置:
D <------C <------B <------A (HEAD, foo, remote/foo)
Why does it look like my local foo is ahead of origin/foo?
这是我无法回答的问题。在变基之后,我会再次期望 HEAD
== foo
== remote/foo
但事实并非如此。为什么在 foo
变基到 remote/foo
之后后者似乎落后了?
您在 pull --rebase
之前拥有的是:
x--x--x (foo, HEAD, origin/foo)
\
y--y (actual origin/foo)
当您 pull --rebase
时,您要求在 origin/foo
之上重播您的本地提交:
foo
在 origin/foo
处 reset/checked(在 FETCH_HEAD
中获取),并且由于您的提交 'x
' 已经是新更新 FETCH_HEAD
, foo
只是快进:
x--x--x--y--y (foo, HEAD, FETCH_HEAD)
|
(origin/foo)
origin/foo
未 更改的事实是 git older than 1.8.4 (found for instance in Ubuntu Precise 12.04 的典型特征,它与旧的 git-core
1.7.9.5 一起提供)
一个简单的 git fetch
应该足以更新 origin/foo
,而不仅仅是 FETCH_HEAD
.
较新的 git (1.8.4+) 会同时更新 FETCH_HEAD
和 origin/foo
,从而使额外的 git fetch
变得多余。
注意:对于 Git 2.12(2017 年第一季度),这种情况 (pull --rebase) 将是一个简单的快进合并。
参见 commit 33b842a (29 Jun 2016) by Junio C Hamano (gitster
)。
(由 Junio C Hamano -- gitster
-- in commit 2fb11ec 合并,2016 年 12 月 19 日)
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.