我知道有些人默认使用git pull --rebase
而其他人坚持不使用它。我相信我理解合并和变基之间的区别,但我试图将其置于git pull
的上下文中。它只是不想看到很多合并提交消息,还是有其他问题?
答案 0 :(得分:683)
我想提供一个关于“git pull --rebase”实际意味着什么的不同观点,因为它似乎有时会迷失。
如果你曾经使用过Subversion(或CVS),你可能习惯了“svn update”的行为。如果您有提交更改并且提交失败,因为已在上游进行了更改,则您将“svn update”。 Subversion通过合并上游更改来继续进行,可能会导致冲突。
Subversion刚刚做了什么,基本上是“拉动 - 基础”。将本地更改重新制定为相对于较新版本的行为是其“重新定位”部分。如果你在失败的提交尝试之前完成了“svn diff”,并且之后将得到的diff与“svn diff”的输出进行比较,那么两个差异之间的差异就是变基操作所做的。
在这种情况下,Git和Subversion之间的主要区别在于,在Subversion中,“您的”更改仅作为工作副本中的非提交更改存在,而在Git中,您在本地实际提交。换句话说,在Git中你已经分享了历史;你的历史和上游历史已经分歧,但你有一个共同的祖先。
在我看来,在正常情况下让你的本地分支只是反映上游分支并对其进行持续开发,正确的做法总是“--rebase”,因为这就是你在语义上实际上< EM>操作。你和其他人正在破坏分支的预期线性历史。事实上,其他人在您尝试推动之前碰巧略微推动是无关紧要的,并且对于每次这样的事故导致合并的事故似乎都适得其反。
如果你真的觉得无论出于什么原因需要某个分支,那么我认为这是一个不同的问题。但除非你有特定和积极的愿望以合并的形式表示你的变化,否则我认为默认行为应该是“git pull --rebase”。
请考虑其他需要观察和了解项目历史的人。您是否希望历史上散布着数以百计的合并,或者您是否只想要选择少数合并来代表有意发散的开发工作?
答案 1 :(得分:511)
时应使用
git pull --rebase
确实 - 为什么不呢?它更清楚,并且不会在您的提交中强加逻辑分组。
好的,我想它需要一些澄清。在Git中,您可能知道,我们鼓励您进行分支和合并。您提取更改的本地分支和远程分支实际上是不同的分支,git pull
是关于它们的合并。这是合理的,因为你不经常推动并且通常会在它们构成一个完整的特征之前积累一些变化。
然而,有时 - 无论出于什么原因 - 你认为如果这两个 - 远程和本地 - 是一个分支实际上会更好。就像在SVN中一样。正是git pull --rebase
发挥作用的地方。您不再合并 - 您实际上在远程分支上提交。这就是它的实际意义。
是否危险是你是否将本地和远程分支视为一个不可分割的问题。有时它是合理的(当你的变化很小时,或者如果你处于强劲发展的开始阶段,当小的提交带来重要的变化时)。有时它不是(当你通常创建另一个分支,但你懒得这样做)。但这是一个不同的问题。
答案 2 :(得分:153)
或许最好的解释方法是举例:
git checkout master && git pull
。师父已经是最新的了。git checkout master && git pull
。师父已经是最新的了。git merge topic-branch-A
git merge topic-branch-B
git push origin master
git push origin master
,因为它不是快进合并而被拒绝。git pull --rebase origin master
git push origin master
,大家都很高兴他们在将来查看日志时不必阅读无用的合并提交。请注意,要合并的特定分支与示例无关。在这个例子中,Master可以很容易地成为发布分支或dev分支。关键是爱丽丝&amp; Bob同时将其本地分支合并到共享远程分支。
答案 3 :(得分:137)
我认为在与同一分支上的其他人合作时,您应该使用git pull --rebase
。你正在工作→提交→工作→提交周期,当你决定推动你的工作时,你的推动被拒绝,因为在同一个分支上有并行工作。此时,我始终执行pull --rebase
。我不使用squash(以展平提交),但我重新设置以避免额外的合并提交。
随着你的Git知识的增加,你发现自己在历史上看起来比我用过的任何其他版本控制系统要多得多。如果你有大量的小合并提交,很容易失去你历史上正在发生的大局的焦点。
这实际上是我唯一一次进行变基(*),而我的工作流程的其余部分都是基于合并的。但只要你最常见的提交者这样做,历史最终会看起来好多了。
(*)
在教授Git课程的同时,我让一名学生逮捕了我,因为在某些情况下我也主张修改功能分支。并且他已经阅读了这个答案;)这种变基也是可能的,但它总是必须根据预先安排/商定的系统,因此不应该“始终”应用。那时我通常也不会做pull --rebase
,这就是问题所在;)
答案 4 :(得分:47)
我认为没有理由不使用pull --rebase
- 我特意向Git添加了代码以允许我的git pull
命令始终对上游提交进行重新绑定
在浏览历史记录时,知道处理该功能的人/ gal何时停止同步,这一点从未有意思。当他/她这样做时,它对于那个/ gal可能是有用的,但这就是reflog
的用途。它只会为其他人增加噪音。
答案 5 :(得分:24)
请记住:
因此,选择您想要处理分支的方式。
你最好知道merge和rebase之间的区别:)
答案 6 :(得分:7)
我认为这归结为个人偏好。
你想在推动改变之前隐藏你的愚蠢错误吗?如果是这样,git pull --rebase
是完美的。它允许您稍后将提交压缩到几个(或一个)提交。如果您在(未按下的)历史记录中进行了合并,那么稍后再进行git rebase
就不那么容易了。
我个人并不介意发布我所有的愚蠢错误,所以我倾向于合并而不是rebase。
答案 7 :(得分:6)
git pull --rebase
可能会隐藏协作者git push --force
的历史记录重写。如果您知道在其他人做同样的事情之前忘记推送您的提交,我建议您仅使用git pull --rebase
。
如果您没有提交任何内容,但您的工作空间不干净,请git stash
前git pull
。这样你就不会默默地重写你的历史(这可能会默默地放弃你的一些工作)。
答案 8 :(得分:0)
一个实践案例是使用Bitbucket PR时。 有公关开放。
然后,您决定将PR远程分支重新建立在最新的Master分支上。这将更改PR的提交ID。
然后您要向PR分支添加新的提交。
由于首先使用GUI重新建立了远程分支的基础,因此您需要将PC上的本地分支与远程分支同步。
在这种情况下,git pull --rebase
就像魔术一样。
在git pull --rebase
之后,您的远程分支和本地分支具有相同的历史记录和相同的提交ID。
现在,您可以很好地推送新的提交,而无需使用力或任何东西。