我什么时候应该使用git pull –rebase?


When should I use git pull --rebase?

我知道有些人默认使用git pull --rebase,还有一些人坚持不使用。我相信我理解合并和再平衡之间的区别,但我正试图把它放在git pull的上下文中。它只是不想看到大量的合并提交消息,还是有其他问题?


我想对"git pull-rebase"的实际含义提供一个不同的观点,因为它有时似乎会丢失。

如果您曾经使用过Subversion(或CVS),那么您可能会习惯于"SVN更新"的行为。如果您有要提交的更改,并且提交失败,因为更改是在上游进行的,那么您将"SVN更新"。颠覆通过将上游变更与您的变更合并来进行,可能导致冲突。

颠覆者刚刚做的,本质上是"拉——再平衡"。重新制定与新版本相关的本地更改的行为是它的"重新平衡"部分。如果在提交尝试失败之前执行了"svn diff",并将结果diff与随后的"svn diff"输出进行比较,则两个diff之间的差异就是重新平衡操作所做的。

在这种情况下,Git和Subversion之间的主要区别在于,在Subversion中,"您的"更改仅作为工作副本中未提交的更改存在,而在Git中,您在本地有实际提交。换句话说,在Git中,你已经分叉了历史;你的历史和上游的历史已经分化了,但是你有一个共同的祖先。

在我看来,在通常情况下,让您的本地分支仅仅反映上游分支并对其进行持续开发,正确的做法始终是"重新平衡",因为这就是您在语义上实际所做的。你和其他人正在窃取一个分支的预期线性历史。事实上,有人在你尝试推之前稍微推了一下,这是无关紧要的,而且对于每一次这样的时间事故来说,导致历史上的合并似乎都是适得其反的。

如果你真的因为任何原因觉得有必要做一个分支,在我看来这是一个不同的问题。但是,除非您有一个特定的、积极的愿望以合并的形式来表示您的更改,在我看来,默认行为应该是"git pull——rebase"。

请考虑其他需要观察和了解您的项目历史的人。你想让历史上到处都是成百上千的合并,还是只想选择少数几个代表有意不同开发努力的真正合并的合并?


你应该使用git pull --rebase

  • 你的改变不应该有一个单独的分支

事实上——那为什么不呢?更清楚的是,它不会对您的提交进行逻辑分组。

好吧,我想需要澄清一下。在Git中,正如您可能知道的,我们鼓励您进行分支和合并。您的本地分支(您将更改拉入其中),而远程分支实际上是不同的分支,而git pull是关于合并它们的。这是合理的,因为您不经常推送,并且通常在它们构成一个完整的特性之前积累一些更改。

然而,有时——不管什么原因——你认为如果这两个——远程和本地——是一个分支,实际上会更好。就像在SVN。正是在这里,git pull --rebase开始发挥作用。您不再合并——实际上是在远程分支的顶部提交。这就是它真正的意义所在。

它是否危险是一个问题,你是否把本地和远程分支视为一件不可分割的事情。有时候这是合理的(当您的变更很小时,或者如果您正处于一个健壮的开发的开始时,当重要的变更是由小的提交带来的时候)。有时不是这样(通常你会创建另一个分支,但你太懒惰了,不能这样做)。但这是另一个问题。


也许最好的解释方法是举个例子:

  • Alice创建了主题分支A,并处理它
  • Bob创建了无关的主题分支B,并处理它
  • 艾丽丝做的是埃多克斯1〔0〕。主控形状已经是最新的。
  • Bob做git checkout master && git pull。主控形状已经是最新的。
  • 艾丽丝做埃多克斯
  • Bob做git merge topic-branch-B
  • 鲍勃在艾丽丝面前做埃多克斯(4)
  • Alice做的是git push origin master,这是被拒绝的,因为它不是一个快速前进的合并。
  • Alice查看origin/master的日志,发现commit与她的无关。
  • 艾丽丝做埃多克斯(6)
  • Alice的合并提交被取消,Bob的提交被取消,Alice的提交在Bob的提交之后应用。
  • Alice做了git push origin master,每个人都很高兴,他们在将来查看日志时不必读取无用的合并提交。
  • 请注意,要合并到的特定分支与示例无关。本例中的master可以很容易地成为发布分支或开发分支。关键是Alice&Bob同时将本地分支合并到共享的远程分支。


    我认为你应该在同一个分支上与其他人合作时使用git pull --rebase。你在你的工作中→提交→工作→提交周期,当你决定推动你的工作时,你的推动被拒绝了,因为在同一个分支上有并行工作。在这一点上,我总是做一个pull --rebase。我不使用squash(扁平提交),但我重新设置了基以避免额外的合并提交。

    随着您的Git知识的增加,您发现自己比我使用的任何其他版本控制系统都更关注历史。如果你有大量的小合并承诺,很容易失去历史上发生的更大情况的焦点。

    这实际上是我唯一一次重新设定(*)的值,而我的其余工作流程是基于合并的。但是,只要你最频繁的提交者这样做,历史最终看起来会好很多。

    (*)在教一门Git课程的时候,有个学生逮捕了我,因为我也主张在某些情况下重新设置功能分支。他已经读过这个答案;)这种重新平衡也是可能的,但它必须始终按照预先安排/商定的系统,因此不应"总是"应用。在那个时候,我通常也不做pull --rebase,这就是问题所在;)


    我不认为有任何理由不使用pull --rebase--我专门在git中添加了代码,以允许我的git pull命令总是针对上游提交重新平衡。

    当回顾历史的时候,我们永远不会感兴趣的是,正在研究这个功能的家伙/女孩什么时候停止了同步。当他/她这样做的时候,这可能对他/她有用,但这就是reflog的目的。这只是给其他人增加噪音而已。


    记住:

    • 拉=提取+合并
    • pull--rebase=fetch+rebase

    所以,选择您想要处理分支的方式。

    你最好知道merge和rebase的区别:)


    我认为归根结底是个人喜好。

    你想在改变之前隐藏你的愚蠢错误吗?如果是这样,git pull --rebase是完美的。它允许您稍后将提交压缩为几个(或一个)提交。如果你合并了你的(未公布的)历史,那么做一个git rebase后一个就不那么容易了。

    我个人并不介意公布我所有的愚蠢错误,所以我倾向于合并而不是重新平衡。


    git pull --rebase可以对合作者git push --force隐藏历史重写。我建议使用git pull --rebase,前提是你知道你忘了在别人之前推动你的承诺。

    如果你什么都没做,但是你的工作空间不干净,就在去之前去12号。这样,你就不会默默地重写你的历史了(这可能会使你的一些工作陷入沉默)。