“理解”;git pull--重新设置基“;vs";git rebase“;

“理解”;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

根据我对git pull--rebase origin master的理解,它应该相当于运行以下命令:

(from branch master):  $ git fetch origin
(from branch master):  $ git rebase origin/master
我似乎发现有些情况下,这并不像预期的那样有效。在我的工作区中,我有以下设置:

  • 分支机构
    origin/master
    参考远程
    origin
  • 分支
    master
    设置为跟踪
    origin/master
    ,并通过多次提交位于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%可复制的。但是,当它对提交有效时,它每次都有效

注意:My
git 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
,它是commit
E
HEAD
feature
)和
master
的分叉点也是commit
B
,让commit
I
通过
K
像往常一样在
E
之后进行复制


如果删除了一些提交,则说明此过程中出现了问题,但我看不出是什么。

您不应该重新设置远程跟踪分支
源代码/master
本身的基址,而应该在不影响该远程分支的(跟踪)副本的情况下将其向前推进。我还没有检查手册中是否有正确的调用,但可能是签出-b以一个新的临时名称签出该分支,并将该临时分支重新设置到您当前的头上。我不是将
origin/master
重定基址,而是将当前分支
master
重定基址到
origin/master
。根据我的理解,这实际上应该将
带到
源代码/主代码
的顶端,并将位于
主代码
顶端的提交重新应用到分支。基本上,在
master
上重新编写新的提交,就好像它们发生在
origin/master
的更改之后一样。您的(本地)git版本是什么?我问这个问题是因为我记得(有点模糊,还没有回去检查)在几个2.x版本的
git pull
中有一个自动分叉点重新基线错误,知道这个版本可能会使检查变得更容易。我目前的git版本是2.7.0,自从找到它之后我就没有更新过它