“理解”;git pull--重新设置基“;vs";git rebase“;
根据我对git pull--rebase origin master的理解,它应该相当于运行以下命令:“理解”;git pull--重新设置基“;vs";git rebase“;,git,version-control,rebase,Git,Version Control,Rebase,根据我对git pull--rebase origin master的理解,它应该相当于运行以下命令: (from branch master): $ git fetch origin (from branch master): $ git rebase origin/master 我似乎发现有些情况下,这并不像预期的那样有效。在我的工作区中,我有以下设置: 分支机构origin/master参考远程origin 分支master设置为跟踪origin/master,并通过多次提交位于m
(from branch master): $ git fetch origin
(from branch master): $ git rebase origin/master
我似乎发现有些情况下,这并不像预期的那样有效。在我的工作区中,我有以下设置:
- 分支机构
参考远程origin/master
origin
- 分支
设置为跟踪master
,并通过多次提交位于master之后origin/master
- 分支
设置为跟踪本地分支功能
,并通过多次提交在主机
之前主机
(from branch master): $ git pull --rebase
(from branch master): $ git checkout feature
(from branch feature): $ git pull --rebase
此时,我在功能
上进行的几次提交现在已经丢失。现在,如果我重置我的位置,并执行以下操作:
(from branch feature): $ git reset --hard HEAD@{2} # rewind to before second git pull
(from branch feature): $ git rebase master
提交已正确应用,并且我在功能上的新提交仍然存在。这似乎与我对git-pull
工作原理的理解直接矛盾,除非git-fetch.
做了一些出乎我意料的事情
不幸的是,对于所有提交,这不是100%可复制的。但是,当它对提交有效时,它每次都有效
注意:Mygit pull--rebase
这里实际上应该理解为一个--rebase=preserve
,如果这很重要的话。我的~/.gitconfig
中有以下内容:
[pull]
rebase = preserve
(编辑,2016年11月30日:另见至。现在几乎可以肯定这是由于分叉点选项。)
手动和基于pull
的git-rebase
之间有一些区别(现在在2.7版本中比在git-merge-base
中的--fork-point
选项之前的git版本更少)。而且,我怀疑你的自动保存合并可能与此有关。这有点难以确定,但事实上,你的本地分支机构跟随你的另一个本地分支机构,这是非常有启发性的。同时,旧的git pull
脚本最近也用C重写了,因此很难看到它的功能(尽管您可以将环境变量git_TRACE
设置为1
,使git在内部运行命令时向您显示命令)
在任何情况下,这里有两个或三个关键项目(取决于您如何计算和划分这些项目,我将其分成三个):
git pull
运行git fetch
,然后按照指令执行git merge
或git rebase
,但当它运行git rebase
时,它使用新的分叉点机制“从上游rebase恢复”
- 当
git-rebase
在没有参数的情况下运行时,它有一个调用fork-point机制的特殊情况。使用参数运行时,除非使用--fork-point
明确请求,否则将禁用fork-point机制
- 当
git-rebase
被指示保留合并时,它使用交互式rebase代码(非交互式)。我不确定这在这里是否真的重要(因此上面的“可能涉及”)。通常情况下,它会使合并变平,并且只有交互式重新基础脚本有代码来保留合并(由于没有其他方法来处理合并,因此此代码实际上会重新执行合并)
这里最重要的项目(当然)是分叉点代码。这段代码使用reflog来处理通过绘制提交图的一部分来最好地显示的情况
在正常(不需要分叉点的东西)的重基情况下,您有如下内容:
... - A - B - C - D - E <-- origin/foo
\
I - J - K <-- foo
... - A - B - C - D - E <-- origin/foo
\ \
\ I' - J' - K' <-- foo
\
I - J - K [foo@{1}: reflog for foo]
B' - C - D - E <-- origin/foo
/
... - A - B <-- [origin/foo@{n}]
\
I - J - K <-- foo
当上游-origin/foo
本身被重定基时,就会出现此方法的问题。比如说,在origin
上,有人强行推动B
以一个新的B'
副本替换,该副本具有不同的提交措辞(可能还有一个不同的树,但是,我们希望,通过-K
,不会影响我们的I
)。现在的起点如下所示:
... - A - B - C - D - E <-- origin/foo
\
I - J - K <-- foo
... - A - B - C - D - E <-- origin/foo
\ \
\ I' - J' - K' <-- foo
\
I - J - K [foo@{1}: reflog for foo]
B' - C - D - E <-- origin/foo
/
... - A - B <-- [origin/foo@{n}]
\
I - J - K <-- foo
然后第一个fetch
引入一些提交,并使origin/master
指向新提示:
C - D - E <-- origin/master
/
... - A - B <-- master, origin/master@{1}
\
I - J - K <-- feature
第二个fetch来自您自己,并且完全跳过了no-op/skipped,将其作为第二个rebase的输入。--on
目标是master
,它是commitE
,HEAD
(feature
)和master
的分叉点也是commitB
,让commitI
通过K
像往常一样在E
之后进行复制
如果删除了一些提交,则说明此过程中出现了问题,但我看不出是什么。您不应该重新设置远程跟踪分支源代码/master
本身的基址,而应该在不影响该远程分支的(跟踪)副本的情况下将其向前推进。我还没有检查手册中是否有正确的调用,但可能是签出-b以一个新的临时名称签出该分支,并将该临时分支重新设置到您当前的头上。我不是将origin/master
重定基址,而是将当前分支master
重定基址到origin/master
。根据我的理解,这实际上应该将头
带到源代码/主代码
的顶端,并将位于主代码
顶端的提交重新应用到分支。基本上,在master
上重新编写新的提交,就好像它们发生在origin/master
的更改之后一样。您的(本地)git版本是什么?我问这个问题是因为我记得(有点模糊,还没有回去检查)在几个2.x版本的git pull
中有一个自动分叉点重新基线错误,知道这个版本可能会使检查变得更容易。我目前的git版本是2.7.0,自从找到它之后我就没有更新过它