为什么git pull默认执行合并而不是变基?


71

请考虑以下情况:

  • 您有一个git存储库的克隆
  • 您有一些本地提交(尚未推送到任何地方的提交)
  • 远程存储库中有尚未提交的新提交

所以像这样:

未合并的提交

如果git pull使用默认设置执行,则会得到以下内容:

合并提交

这是因为git执行了合并。

不过,还有另一种选择。您可以告诉pull做一个rebase:

git pull --rebase

然后您会得到:

重新设定

在我看来,经过重新设计的版本具有许多优势,主要集中在保持代码和历史记录的整洁方面,因此我对git默认情况下进行合并感到震惊。是的,您本地提交的哈希值将被更改,但这似乎为您获得较简单的历史记录付出了很小的代价。

但是,我绝不建议这某种程度上是错误的或错误的默认值。我只是在想为什么可能首选默认合并的原因而已。我们是否对为什么选择它有任何见识?有没有使其更适合用作默认设置的好处?

这个问题的主要动机是,我的公司正在尝试建立一些关于如何组织和管理存储库的基线标准(希望更像是准则),以使开发人员更容易地访问以前从未使用过的存储库。我有兴趣提出一个案例,我们通常应该在这种情况下进行基准调整(并可能建议开发人员将其全局配置默认设置为进行基准调整),但是如果我反对这样做,我肯定会问为什么要进行基准调整?如果太好了,则使用默认值。所以我想知道我是否缺少某些东西。

有人提出这个问题是重复的,为什么这么多的网站更喜欢“ git rebase”而不是“ git merge”?; 但是,这个问题与这个问题有些相反。它讨论了在合并基础上进行重组的优点,而该问题询问了在合并基础上进行合并的好处。那里的答案反映了这一点,着重于合并问题和资产重组的好处。



另一个问题是,如果您不小心提交给master,然后执行合并的pull,即使合并看起来很正常,两个master也可能不同步。这就是为什么我的pull别名包括--ff-only的原因。
Ixrec

如果sourcetree更改了其图形视图,从而以不同的方式显示了重新设置/合并,您将切换到合并吗?
伊万

1
@Ewan SourceTree不应更改其图形视图。它准确地表示图形。
jpmc26 2016年

4
对于欺骗性选民,请注意,我所接受的答案中的内容绝对不会出现在您声称是重复的问题中。
jpmc26'1

Answers:


56

很难确定为什么合并是默认的,而没有做出决定的人的来信。

这是一个理论...

Git不能假定-p每次拉动都可以。听听声音。“重新调整拉力。” 如果您使用拉取请求或类似请求,这听起来似乎是错误的。您是否会基于拉取请求?

在一个不仅仅使用Git进行集中式源代码控制的团队中...

  • 您可以从上游和下游拉动。有些人从下游,贡献者等那里做很多事情。

  • 您可以与其他开发人员密切协作来开发功能,从其他开发人员或共享主题分支中提取功能,有时仍从上游进行更新。如果总是变基,那么最终将更改共享历史记录,更不用说有趣的冲突周期了。

Git是为一个高度分散的大型团队而设计的,每个人都不是一个单一的中央仓库。因此默认设置是合理的。

  • 默认情况下,不知道何时可以重新设置基础的开发人员将合并。
  • 开发人员可以根据需要进行调整。
  • 做很多事情并且做很多事情的提交人都会得到最适合他们的默认值。

为了表明您的意图,这里有指向Linus Torvalds的一封著名电子邮件的链接,其中包含他对何时不应该重新建立基础的看法。 Dri-devel git pull电子邮件

如果您遵循整个线程,您会看到一个开发人员正在从另一位开发人员撤出,而Linus正在从他们两者撤出。他说得很清楚。由于他可能决定了Git的默认设置,因此这可以解释原因。

现在,很多人都在集中使用Git,一个小团队中的每个人都只能从上游中央存储库中拉出并推送到同一远程。此方案避免了某些基础不好的情况,但通常不会消除它们。

建议:不要制定更改默认值的策略。每当您将Git与一大批开发人员放在一起时,有些开发人员将不会对Git这么深刻的理解(包括我自己)。他们将前往Google,获得食谱建议,然后想知道为什么有些事情不起作用,例如,为什么git checkout --ours <path>得到的文件版本错误?您随时可以修改您的本地环境,创建别名等以适合您的口味。


5
+1不改变默认的-而不是滚动您自己的Git工作流程,它可能更好地抓住一个存在(例如,任何由Atlassian的记录的那些的atlassian.com/git/tutorials/comparing-workflows/...
罗博教堂

1
感谢您的回答。我缺少从下游拉出的信息。同样,有趣的是,您提供的链接确实鼓励了我想要实现的目标:“人们可以(可能应该)重新构建他们的私有树(他们自己的工作)。”
jpmc26 2016年

2
@jpmc太好了。确实。对私人树木进行重新定价可以使许多分散注意力的东西脱离共享的历史记录。我做 明确何时不执行此操作很重要。
joshp

“有些开发人员对Git的了解并不深”。Rebase不是Git的超级功能(“深度”等)。您真的认为这件事很难理解吗?我认为这应该是引发开发人员能力不足的诱因。
维克多·亚雷玛

15

如果您阅读git联机帮助页以进行重新设置,它会显示

对其他人基于其工作的分支重新建立基础(或进行任何其他形式的重写)是一个坏主意:该分支下游的任何人都必须手动修复其历史记录。本节从下游的角度说明如何进行修复。但是,真正的解决方法是首先避免对上游进行重新调整。

我认为这足以说明其根本不使用rebase的原因,更不用说每次拉动都会自动执行它了。有些人认为改基是有害的。也许根本不应该将它放到git中,因为它似乎所做的只是美化历史记录,这对于任何仅以保存历史为基础的SCM都是不必要的。

当您说“保持……历史的整洁”时,认为您错了。它可能看起来更好,但是对于设计用于保留修订历史的工具而言,保留每次提交要干净得多,这样您就可以看到发生了什么。之后清理历史就像抛光古铜,使丰富的古董看起来像闪亮的复制品:-)


3
@Ewan恕我直言,“不起作用,但看起来很漂亮”是应该完全保留给时装业而不是IT业的东西。恕我直言git应该删除它,因为它显然会鼓励太多人认为样式比实质更重要。
gbjbaanb

12
我会反对您的建议,即保持历史记录干净无用。不是。存储库历史记录供人类使用,因此,使其具有可读性具有很多价值。在我的特定用例中,我们甚至打算让非开发人员的项目经理能够读取历史记录。干净的历史记录只能帮助您解决此问题,它可以帮助从未见过代码基础并且必须深入研究并修复错误的新开发人员了解特定代码区域中发生的情况。
jpmc26 2016年

3
代码首先存在,并且首先要由机器执行(可能在编译之后)。综上所述,我们将得出结论,代码的可读性并不重要,因为没有多少可读性会解​​决理解代码的困难。我从来没有建议应压缩任何东西。我只是在说很难散布到很多交叉路径的复杂图形,因此值得投入一些钱来使您的历史保持相当干净。还要注意,线性历史记录更有助于利用blame和bisect等git工具。
jpmc26 2016年

6
文档没有说“不变基”。它说:“不要改变别人上游的变化。” 两者之间有天壤之别。Linus本人建议对组织历史进行一些调整,如已接受的答案中的链接所示。以及任何工具如何知道哪些提交是不相关的(特别是如果工具难以分析非线性历史记录!),以及如何知道要与哪个提交进行比较(尤其是无法挖掘历史记录!)?您在警告特定情况时要谨慎至极端。
jpmc26 2016年

4
如果包括开发人员所做的每一次提交,您绝对不希望“保留修订历史”。按照这种逻辑,每次击退空格键时,我们也应该记录代码的原始版本。每次提交都应该是最小且完整的更改,这样仍可以使整个项目保持稳定状态。如果后来发现您的原始提交有问题,那么重新创建/修改/修改提交要比创建另一个提交更好。但是,另请参见mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html
Mikko Rantalainen

12

您是对的,假设您只有一个本地/更改的存储库。但是,例如,考虑有第二台本地PC。

一旦将本地/修改后的副本推送到其他地方,重新设置基准将使这些副本搞砸。当然,您可以强行推动,但这很快变得很复杂。如果其中一个或多个具有另一个全新的提交会发生什么?

如您所见,这是非常实际的情况,但是在我看来,基本策略在非特殊/协作情况下似乎更加实用。


第二个区别:合并策略将保持清晰且时间一致的结构。重新设置基准之后,很可能旧的提交可能会跟随新的更改,从而使整个历史及其流程变得难以理解。


1
“在重新设置基准之后,很可能旧的提交可能会跟随新的更改” –但是,合并也会发生这种情况,这就是为什么(可能)需要漂亮的图来理解它。提交的时间可能早于将其带入此分支的合并的时间。
史蒂夫·杰索普

6

最大的原因可能是默认行为应在公共存储库中“正常工作”。依靠其他人已经合并的历史将给他们带来麻烦。我知道您是在谈论私有存储库,但是一般来说git不知道或不在乎什么是私有存储或公共存储,因此所选的默认值将是两者的默认值。

git pull --rebase在私人仓库中使用了很多东西,但是即使在那儿它也有潜在的缺点,那就是我的历史HEAD不再反映我实际使用的那棵树。

因此,举一个大例子,假设我总是运行测试并确保在提交之前它们通过。在执行git pull --rebase完以后,它的相关性降低了,因为我的每个提交中的树都已经通过测试不再是真的。只要更改不会以任何方式干扰,并且我提交的代码已经过测试,那么大概可以通过测试,但是我们不知道,因为我从未尝试过。如果持续集成是您工作流程的重要组成部分,那么正在被CIed的存储库中的任何类型的基础都会令人困扰。

我并不介意,但是这确实使某些人感到困扰:他们更喜欢git中的历史记录反映了他们实际工作的代码(或者也许在他们推销时,是经过一些使用后的事实的简化版本) “修复”。

我不知道这个问题是否特别是Linus选择合并而不是默认替换基准的原因。我可能还没有遇到其他缺点。但是,由于他不害羞地在代码中表达自己的意见,所以我敢肯定,这归结于他认为对那些不想过多考虑的人(尤其是那些在公共场所工作的人而不是私人回购)。避免在漂亮的图形中使用平行线,而是使用一条干净的直线来表示发生的并行开发,尽管这是您的首要任务,但这并不是他的首要任务:-)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.