git pull在合并/ rebase步骤之后检查当前分支吗?

时间:2015-12-29 01:48:35

标签: git

git pull的合并/重组步骤将远程跟踪分支合并/重新绑定到当前分支上。

我想知道git pull然后将当前分支检出到工作目录中吗?或者我应该自己看看?

我的问题是我认为合并步骤修改了git存储库中的当前分支,而工作目录尚未与当前分支保持同步,因此需要检查修改后的当前分支进入工作目录。

但我不确定git pull的合并步骤是否已经完成,或者我是否应该在git pull之后自行完成。

2 个答案:

答案 0 :(得分:2)

当前分支 在工作目录中签出。

在合并/ rebase之后,分支已向前移动到另一个提交。

所以是的,git将检查该提交,以便你留在当前分支。

答案 1 :(得分:2)

简短的回答是" no",这实际上是一个完整且技术上正确的答案,但有点不满意并且很可能误导:在所有中例如,最终状态是好像 git已经完成了结账。如果你愿意的话,你可以停在这里。 : - )

长期答案有点长,在现代版本的git中变得复杂,因为您可以将git rebase设置为" autostash"。但我们再次回到git pull运行git fetch后跟git mergegit rebase的事实。

  • fetch步骤更简单,因为它不需要知道或关心工作目录。它会联系指定的 remote (如果您没有指定一个,则从当前分支branch.$branch.remote获取),为该远程提供一些refspec(s) (来自您传递的其他参数,或者您未通过任何配置的配置),并根据需要从远程调用提交和其他对象。这些提交和其他对象被推送到您的存储库中的存储中,在那里它们可以安全地排除在外,但随时可用。一些"远程跟踪"可以更新分支名称,并且在任何情况下,将带来的分支头部放入特殊FETCH_HEAD文件中(特别是,FETCH_HEAD获取与之一起的SHA-1 ID每个分支机构名称)。

    要查看整个名称/ SHA-1 ID映射内容,请运行git ls-remote remote(例如git ls-remote origin)。这将联系远程并从中获取git fetch获取的相同信息,然后在命令窗口中将其打印出来。它对其他任何东西都没有任何改变,所以它只是使用了一点网络带宽,而且在我看来它很有教育意义。 (如果遥控器上有很多分支和标签,您可能需要来回滚动以查看所有输出,或将输出保存在文件或其他任何内容中。)

  • mergerebase步骤是棘手的位置。让我们退出嵌套并考虑两者。我们也只考虑与单个目标合并的情况(即正常的日常合并,而不是git的花式章鱼合并)。

如果你从干净的工作树开始(和索引),那么描述现在发生的事情要容易得多。让我们假设一个干净的工作树开始。

fetch步骤带来了一些提交。 mergerebase找到合适的合并基或rebase目标,然后按照指示执行合并或rebase:

  • 对于合并,git会找到合并基础。通常,这是一个特定的提交。 (在某些情况下,有多个合并基础候选者,git也处理这些,但是不要担心它们。)您可以将此视为您的分支和其他分支分歧的点:

    <--older--time increases as we move right--newer-->
    [see footnote 1]
    
                  o - o       <-- your branch (master)
                /
    ... - o - *
                \
                  o - o - o   <-- their branch (origin/master)
    

    在此图中,每个小o节点表示提交。合并基础是标记为*而非o的提交。您的分支master的提示最多提交位于顶行的最右侧o,其分支origin/master的提示最多提交是最右侧{{1}在底线。

    让我们调用你的分支o的最尖端提交,只是为了具体。 (它有自己独特的SHA-1 ID以及它的真实姓名&#34;,但我们只需称它为A。)让我们来电话合并基础A和其分支B的提示,并重绘该图表:

    C

    要执行合并(当需要合并时),git首先在commit o - A <-- your branch (master) / ... - o - B \ o - o - C <-- their branch (origin/master) 和commit B之间运行diff,就好像你A一样(填写实际内容)当然,git diff B AB的SHA-1;它使用其差异代码的内部版本,而不是简单地读取文字A文本输出。这个差异告诉git&#34;你改变了什么&#34;自公共基础git diff

    接下来,git运行B(当然再次使用内部格式)。这个差异告诉git&#34;他们改变了什么&#34;因为同样的共同基础。

    最后,git尝试组合两个差异。如果你添加了一个文件并且他们没有,那么git会保留你添加的文件。如果您将文件git diff B Cneighbor的拼写更改为neighbour并且他们没有,则会保留您的更改。如果他们删除了您没有触摸的文件,或者从您没有触及的文件中删除了一行,git会保留其更改。如果您将完全相同的更改为README,则git会保留该更改的一个副本(而不是两个副本)。 Git适用于所有&#34;保持&#34;更改基本版本并将结果写入工作树,现在完成合并时没有合并冲突。 git认为,结果已经准备好了。 (请注意,即使您所做的某些更改要求系统保留已删除的文件,git现已删除,也是如此。也就是说,假设他们表示&#34;哦,看看,此文件未被使用,请将其删除&#34; 表示&#34;哦,哎呀,我忘了使用该文件,让我们使用它&#34; .Git并不知道这些变化实际上是冲突的:它可以告诉我们,差异中的线条不会发生碰撞。)

    下一步取决于你是否给了weather.h标志。 2 无论如何都会抑制提交。如果你没有禁止提交,--no-commit提交这个没有明显冲突的变更集,作为&#34;合并提交&#34;有两个父母:

    git merge

    此时,工作树与新提交 o - A ----- M <-- your branch (master) / / ... - o - B / \ / o - o - C <-- their branch (origin/master) 匹配。虽然没有检查 out ,但已将 (已提交)中的检查为合并。

    如果您 M,或者存在合并冲突,则合并将停止并让您修复和/或提交合并。更改只是存在于您的工作目录中。如果您决定提交结果,那将是合并提交。 Git知道这一点,因为它会在合并过程中留下跟踪文件&#34;&#34;。如果您决定取消与--no-commit的合并,则会删除跟踪文件。

  • 对于rebase,git经历了类似的过程。但是,它不是找到合并库,而是找到上游没有的提交集。我们可以再次绘制该图,但是让我们使用不同的节点名称:

    git merge --abort

    在这种情况下,git会发现你的两次提交( A - B <-- your branch (master) / ... - o - o \ C - D - E <-- their branch (origin/master) A)和复制它们(使用B或多或少)。这种机制可能很复杂,所以我们在此注意每个git cherry-pick操作都需要更新工作树并进行新的提交。如果一切顺利,我们会将cherry-pickA的副本以及A' B的副本加载; git将分支名称移动到B';最终的图纸看起来像这样:

    B'

    因为每个cherry-pick步骤都会更新您的工作树并从中提交,所以您的工作树与最终提交 A - B [abandoned] / ... - o - o A' - B' <-- your branch \ / C - D - E <-- their branch 匹配,而不是因为它已经检查 out ,但是因为它已在(已提交)中检查,与合并案例完全相同。

如果你从一个肮脏的工作树开始(或&#34;脏索引&#34;,即任何未签入的更改),那么描述起来就有点难了,但不是太多。我们仍然有两个案例:

  • 对于合并,git仍会尝试合并您的更改及其更改,但它会尝试执行此操作,同时保留其他未提交的更改。如果成功,它会像往常一样从结果中提交,除非像往常一样被禁止。如果它失败了,它会像往常一样停止并让你清理混乱。

    关于这一点的好处是,即使从干净的工作树合并失败,您有时也可以生成有效的合并。关于这一点的坏处在于,当你不是故意的时候,它很容易做到这一点,并且随着你的变化和他们的变化一起变得非常难以退出。它通常只是一个坏主意:提交或藏匿,然后从一个干净的状态合并,如果你愿意,可以与B'合并。然后,您可以在执行任何修复后运行测试并执行自己的提交。 (请注意,您还可以在合并提交时使用--no-commit。)

  • 对于rebase,如果工作树不干净,通常git commit --amend将拒绝运行。这使得这很容易。但是,由于git 1.8.4,git rebase现在具有可配置的rebase设置。如果你设置了这个,那么你的rebase.autostash将在这种情况下为你运行rebase,然后进行rebase,然后(如果一切顺利)为你弹出藏匿。这种模式有一个烦人的(但不是致命的)错误,直到git 2.0.1才得到修复,我建议一般反对它 - 我认为最好只做一个检查点提交,然后清理它后来的清理通行证(在#34之前通过清理通常会很好;最终确定&#34;提交,这是时候挤掉临时检查站;在那之前,他们自然地进行自然改造,没有任何骚扰自动驾驶的危险)。

1 虽然图表说&#34;时间增加到右边&#34;但从技术上讲,右边的节点实际上只是左边节点的后继节点。当您从远程提取提交时尤其如此。这些提交中的时间戳是在其他计算机上完成的,即使你很擅长保持自己的计算机与某个原子钟同步,谁知道他们的时钟是/是/是正确的?那些时间戳可能完全被打破。时间顺序无法保证,只是&#34;可能&#34;。

2 除了git stash之外,--no-commit还带有git merge标志,这有两个副作用:(1)最终提交不是合并提交完全和(2)在完成合并的所有常规工作之后,--squash在没有提交的情况下停止(就像git merge一样)。也就是说,--no-commit内部做的是阻止最终提交停止--squash编写特殊状态文件,告诉git它在中间合并。这样,您之后必须执行的手动提交是普通的非合并提交。