Git樱桃选择vs合并工作流

假设我是一个回购的维护者,我想从一个贡献者那里获得更改,有几个可能的工作流程:

  1. cherry-pick每次从远程提交(按顺序)。在这种情况下,git将提交记录为与远程分支无关。
  2. merge分支,拉入所有更改,并添加一个新的“冲突”提交(如果需要)。
  3. I merge每个远程分支的提交都是单独的(同样是按顺序),允许为每个提交记录冲突,而不是将所有冲突归为一个。
  4. 为了完整起见,你可以使用rebase(和cherry-pick选项一样吗?),但我的理解是,这可能会让贡献者感到困惑。也许这就排除了第一种选择。

在2和3中,git都记录了提交的分支历史,这与1不同。

所描述的使用__ABC0或merge方法之间的利与弊是什么?我的理解是方法2是标准的,但我觉得用一个“冲突”合并来解决一个大的提交,不是最干净的解决方案。

170129 次浏览

rebase(和cherry-pick)和merge都有各自的优点和缺点。我在这里支持merge,但两者都值得理解。(请在这里查找另一个论证良好的回答,枚举了优先使用rebase的情况。)

出于几个原因,merge优先于cherry-pickrebase

  1. 鲁棒性。提交的SHA1标识符不仅在自身中标识它,而且还关于它之前的所有其他提交。这可以保证给定SHA1上存储库的状态在所有克隆上都是相同的。(理论上)不可能有人做了看似相同的更改,但实际上破坏或劫持了您的存储库。您可以选择个别的更改,它们可能是相同的,但您不能保证。(作为一个次要问题,如果其他人再次选择同一提交,新的精选提交将占用额外的空间,因为即使你的工作副本最终是相同的,它们也会出现在历史记录中。)
  2. 易用性。人们往往很容易理解merge工作流。rebase倾向于被认为更高级。两者最好都能理解,但不想成为版本控制专家的人(在我的经验中,有许多同事非常擅长自己的工作,但不想花额外的时间)更容易进行合并。

即使是在合并较多的工作流程中,rebasecherry-pick在特定情况下仍然有用:

  1. merge的一个缺点是混乱的历史。rebase防止一长串的提交分散在你的历史记录中,就像你定期合并其他人的更改一样。这实际上是我使用它的主要目的。你想要非常小心的是,永远不要rebase代码,你已经与其他存储库共享。一旦一个提交被pushed,其他人可能已经在它上面提交了,而重基充其量只会导致上面讨论的那种复制。在最坏的情况下,您可能会得到一个非常混乱的存储库和一些微妙的错误,这将花费您很长时间来查找。
  2. cherry-pick对于从你决定放弃的主题分支中抽取一小部分更改非常有用,但你意识到其中有一些有用的部分。

至于更喜欢合并许多变化而不是一个:它只是简单得多。一旦您开始拥有大量的变更集,合并单个变更集就会变得非常乏味。git(以及Mercurial和Bazaar)中的合并解决方案非常非常好。在大多数情况下,即使合并长分支也不会遇到大问题。我通常一次合并所有的东西,只有如果我得到了大量的冲突,我备份并重新运行合并碎片。即使这样,我也会大块大块地做。作为一个非常真实的例子,我有一个同事,他有3个月的变更需要合并,在250000行代码库中有9000个冲突。我们所做的修复工作是每次合并一个月的数据:冲突不会线性增加,并且分块执行会导致的冲突少于9000个。这仍然有很多工作要做,但没有尝试一次做一个。

在我看来,樱桃采摘应该保留在罕见的情况下,它是必要的,例如,如果你做了一些修复直接在'主'分支(主干,主要开发分支),然后意识到它也应该应用于'维护'。你应该基于merge或者rebase(或者“git pull—rebase”)。

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

此外,在git中,你可以同时合并许多分支:也就是所谓的章鱼合并。注意,章鱼合并必须在没有冲突的情况下成功。尽管如此,它还是有用的。

HTH。

Rebase和Cherry-pick是保持干净提交历史的唯一方法。 避免使用合并并避免产生合并冲突。如果你正在使用gerrit,如果需要,将一个项目设置为合并,另一个项目设置为选择模式,然后自己尝试。< / p >