git pull --rebase fork infomation

时间:2016-05-12 14:52:14

标签: git git-rebase git-pull

我们使用git pull --rebase代替git pull。我们在检索服务器上不再显示的fork信息时遇到问题。

假设一个人“推拉”的单个“主”分支。 此外,假设人们修改了不同的文件,并且git没有引发冲突。

这是我的本地分支及其上游之前的图像

      A---B---C local
     /
D---E---F---G server

如果我们使用git pull(标准版),那就是本来会发生的事情

      A---B---C 
     /         \
D---E---F---G---M---

但由于我们使用的是git pull --rebase,如果我没有错,会发生这种情况:

D---E---F---G---A'--B'--C' 

现在我们知道其中一项测试在C'中不再起作用了。我们确信它在C和G都工作。即使没有冲突,如果有两个冗余代码块,也可能发生这种情况,第一个人删除了一个块,而另一个人删除了另一个块。 / p>

通常,要检查的修改是提交A',B',C,F,G中的修改,因为fork发生在E.但是因为我们使用git pull --rebase我们无法知道何时fork发生了,所以我们无法识别集合A',B',C,F,G。

1)知道问题现在只出现在C',有没有办法识别E,因此有一套A',B',C,F,G?

2)如果1)的答案是“否”,那么应该检查什么提交?

1 个答案:

答案 0 :(得分:2)

TL; DR:您可以使用E和reflog信息找到提交git merge-base

你的绘图是正确的,因为rebase的作用是 copy 提交(对于新的,略有不同的提交)。

原始提交在存储库中保留了一段时间(默认情况下一般为30天):它们只是放在视图之外。可以(使用reflogs和/或ORIG_HEAD查找原始C,并从那里找到合并库提交E

如果经常发生这种事情,我建议不要直接使用git pull。实际上,我建议永远不要使用git pull启动,即使需要更多的工作和更多的输入,使用两个单独的基础步骤。这里的想法是明确Git正在做什么,因此更容易插入有用的自动化。 (之后,根据您自己的自动化,如果您发现运行一个命令而不是两个命令更方便,则可以返回使用git pull,有或没有--rebase。)

git pull执行的操作是git fetch,然后是git mergegit rebase。虽然pull有一些额外的花里胡哨,但这确实是它行动的核心。分别执行这两项操作的好处是,它们允许您在fetch之后和merge - 或 - rebase之前检查状态。

(对于merge来说,这远远不那么必要了,因为“合并之前”状态显而易见:只是剥离合并提交并且你有合并前状态。它对rebase更有用因为“合并前”状态允许你分别查看分叉开发的两面,如果你愿意,在允许Git做疯狂和疯狂的事情之前,制作提交的副本。)

让我们在这里重现你的“之前”状态,然后展示什么是rebase真正做到的。以下是“之前”状态,在运行git fetch之后,但在运行git rebase之前,您将拥有该状态:

      A---B---C   <-- HEAD -> branch
     /
D---E---F---G     <-- origin/branch

我添加了指向当前分支的名称HEAD,并将分支重命名为更典型。

git rebase步骤之后,我们有了这个:

      A---B---C            <-- ORIG_HEAD, branch@{1}
     /
D---E---F---G              <-- origin/branch
             \
              A'--B'--C'   <-- HEAD -> branch

通常,观看者(git loggitk --all等)会跳过ORIG_HEADCHERRY_PICK_HEAD等特殊引用。他们还忽略了reflogs(branch@{1})的内容。使用git refloggit log -g或在命令行中添加ORIG_HEAD等名称,您可以指示这些查看者向您显示原件。

如果将这两个步骤分开,则可以轻松保存有关任何特定提交的信息或添加标记(例如临时git tag)。例如,在git fetch之后,您可以标记提交E:找到branchorigin/branch 1 合并基础,并将其标记为:< / p>

$ git tag temp-marker $(git merge-base branch origin/branch)

(假设为sh或bash或类似内容;请注意,为了概括这一点,您可以使用HEAD@{u}代替branchorigin/branch)。

如果您不想混淆用户(“为什么我们所有的存储库中都有一个名为temp-marker的标记?”,请务必删除temp-marker标记(或至少避免推送它)? “),一旦你完成它。

即使你使用git pull --rebase来保持它们的组合,你也可以使用reflog和/或ORIG_HEAD来做同样的事情。 (这里的主要问题是reflog中的数字 - branch@{1}以及ORIG_HEAD本身都会更新。如果你再做一次rebase,ORIG_HEAD现在跟踪那个 rebase而不是你仍然关注的那个。同时如果你对branch进行任何更新,则数字(@{1})递增:现在你需要branch@{2},然后{{1 (还可以使用branch@{3},它会检查记录到branch@{yesterday}的每个更改的日期戳,并使用最新的“昨天”。请参阅{{ 3}}及其链接返回the git reflog documentation,还有git log,以获取详细信息。)

换句话说,一旦你进入这个特定的泡菜,检查branch是否是正确的参考(或branch@{1}仍然是好的)。如果没有,请使用ORIG_HEAD或类似内容找到正确的参考。无论如何,一旦找到它:

git reflog

将找到提交git merge-base branch@{1} origin/branch

1 这假设只有一个合并基础提交。对于我们在这里考虑的所有情况,这应该是真的。只有存在“纵横交错合并”(必须手工制作)才能获得多个合并基础:

E

此处,...--o--*---o--o <-- branch1 \ / X / \ ...--o--*---o--o <-- branch2 branch1之间没有单一的合并基础:两个branch2提交都是合适的合并基础。在具有单个上游分支的正常工作流中不会发生这种情况(因为您无法检出*并对其进行提交)。你将不得不做一些你自己疯狂和疯狂的事情(使用一个临时分支,两个显式合并,至少一次推动)来实现它。

相关问题