2009-08-06 46 views
263

假设我是一个回购的维护者,我想从一个贡献者的变化来拉,有几个可能的工作流程:Git的摘樱桃VS合并工作流程

  1. 我每个cherry-pick从远程提交(为了)。在这种情况下,git将提交记录为与远程分支无关。
  2. I merge该分支,引入所有更改并添加新的“冲突”提交(如果需要)。
  3. I merge每个分别从远程分支提交(再次按顺序),允许为每次提交记录冲突,而不是将所有提交分组为一个整体。
  4. 为了完整起见,您可以做rebase(与cherry-pick选项相同?),但我的理解是这可能会导致撰写者混淆。也许这消除选项1.

在这两种情况下,2和3,git的记录提交的分支历史,不像1.

亲的和反对的使用无论是cherry-pickmerge方法之间描述的是?我的理解是方法2是常态,但我觉得用单个“冲突”合并来解决大规模提交并不是最干净的解决方案。

回答

253

rebase(和cherry-pick)和merge都有它们的优点和缺点。我认为在这里merge,但它是值得理解。 (在这里寻找一个备用中,公认为answer枚举的情况下rebase是优选的。)

merge优于cherry-pickrebase为几个原因。

  1. 健壮性。提交的SHA1标识符不仅标识它本身,而且还标识之前的所有其他提交。这为您提供了一个保证,即给定SHA1中的存储库的状态在所有克隆中都是相同的。 (理论上)有人没有机会做出看起来像是一样的变化,但实际上是破坏或劫持你的存储库。你可以挑选个人变化,他们可能是相同的,但你没有保证。 (作为次要问题,如果其他人再次选择同一次提交,那么新的樱桃挑选的提交将占用额外的空间,因为即使您的工作副本完全相同,它们也会出现在历史记录中。)
  2. 易用性。人们往往很容易理解merge工作流程。 rebase往往被认为更先进。最好是了解这两者,但不想成为版本控制专家的人(根据我的经验,包括许多擅长自己的工作但不想花费额外时间的同事)更容易时间只是合并。

即使合并重的工作流程rebasecherry-pick仍然是有用的特殊情况:

  1. 一个缺点merge是混乱的历史。rebase可以防止在您的历史中散布大量的提交,就像您定期合并其他人的更改一样。事实上,这是我使用它的主要目的。你想成为非常小心,永远不会rebase代码,你已与其他存储库共享。一旦某个提交是push,那么其他人可能会对其进行承诺,而重新绑定最多会导致上面讨论的那种重复。在最糟糕的情况下,最终可能会出现一个非常混乱的存储库和微妙的错误,需要很长时间才能发现。
  2. cherry-pick可用于从主题分支中抽取出一小部分变化,这些主题分支基本上决定放弃,但意识到有几个有用的部分。

至于宁愿合并许多变化:它只是简单得多。一旦开始拥有大量变更集合,就会变得非常繁琐。 git(以及Mercurial和Bazaar中)的合并解决方案非常好。大部分时间你都不会遇到长期分支融合的重大问题。我通常一次合并所有东西,只有如果我得到大量的冲突,我是否备份并重新运行合并零碎。即使那样,我也是以大块的方式做到这一点。作为一个非常实际的例子,我有一位同事对合并进行了3个月的修改,并且在250000行代码库中遇到了9000次冲突。我们所要解决的问题是,一次合并一个月的价值:冲突不会线性增加,并且这样做会导致远远少于少于9000个冲突。这仍然是很多工作,但不是一次尝试一次就能完成。

+1

实际上,理论上Mallory可能会通过创建具有相同SHA1但不同内容的提交来破坏存储库,但实际上可能不会发生。 :) – Bombe 2009-08-07 06:55:08

+1

哈:)我的意思是“理论上赔率很低,你可以依靠它不发生”,但你说得对,它看起来颠倒。 – quark 2009-08-07 14:45:04

+0

您如何看待“merge --squash”? – cmcginty 2009-09-29 04:02:41

84

在我看来,樱桃采摘应该保留在需要它的罕见情况下,例如,如果你直接在'master'分支(树干,主开发分支)上做了一些修复,然后意识到它应该被应用也要'保姆'。您应该将工作流基于合并或rebase(或“git pull --rebase”)。

请记住,从Git(具有不同的SHA-1标识符)角度来看,挑选或重定位提交是不同,因此它与远程存储库中的提交不同。 (Rebase通常可以处理这个问题,因为它检查补丁ID,即更改,而不是提交ID)。

也在git中,你可以一次合并很多分支:所谓的章鱼合并。请注意,章鱼合并必须没有冲突才能成功。尽管如此,它可能有用。

HTH。

+16

+1表示rebase/cherry-picking实际上“复制”了提交,因此失去了与原提交的链接。 – studgeek 2011-09-17 22:34:12

+1

我们以这种方式使用樱桃挑选,专门用于将错误修复(可能非常小的功能)提交移动到现有版本分支中以准备修补程序。跨越多个提交的功能通常保证进入基于主控的发布分支。 – foxxtrot 2011-10-29 02:42:59

+3

@foxxtrot:另一个解决方案是为bug修复创建一个单独的分支,它基于展现这个bug的最老的提交,并且将它合并到'maint'和'master'中......虽然在这种情况下你需要知道所说的bugfix适用于两个分支。 – 2011-10-29 11:41:29

0

Rebase和Cherry-pick是保持清洁提交历史记录的唯一方法。 避免使用合并并避免创建合并冲突。如果您正在使用gerrit,则在必要时将一个项目设置为合并,并将一个项目设置为樱桃模式并尝试自己。

+0

能否详细说明一下。 ... – 2017-12-13 06:34:57