【问题标题】:Git Cherry-pick vs Merge WorkflowGit Cherry-pick vs 合并工作流
【发布时间】:2010-11-17 12:33:00
【问题描述】:

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

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

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

使用所描述的cherry-pickmerge 方法之间的优缺点是什么? 我的理解是方法 2 是常态,但我觉得用单个解决大提交“冲突”合并,不是最干净的解决方案。

【问题讨论】:

    标签: git merge cherry-pick


    【解决方案1】:

    Rebase 和 Cherry-pick 是保持提交历史干净的唯一方法。 避免使用合并,避免产生合并冲突。如果您正在使用 gerrit,请将一个项目设置为 Merge(如有必要),并将一个项目设置为樱桃挑选模式并尝试自己。

    【讨论】:

    • 完全不清楚这如何回答这个问题,也许一些例子会带来一些启示。
    • 你的历史看起来很直接的事实并不意味着它会更容易理解。
    • 合并是清除历史记录的常用方法。 Cherry-pick and rebase 主要用于必须修改历史的情况。什么意思,合并应该永远是首选。导致 rebase 更改了comit sha`s 当您与遥控器和多人一起工作时非常危险。
    • 这家伙应该得到一枚奖章。他知道他会继续被否决,但这是正确的答案。荣誉。
    • 对不起,我直到现在才看到这些 cmets,请在结束之前在您的测试环境中尝试一下,然后做适合您的事情!我有大约 600 名开发人员为多个产品分支做出贡献,我不在乎开发人员在本地工作区做什么,当提交更改以进行集成时,它应该能够选择开发分支或有时发布或修复错误分支。仅供参考...我使用 Gerrit。
    【解决方案2】:

    在我看来,樱桃采摘应该保留在需要它的极少数情况下,例如,如果您直接在“主”分支(主干,主开发分支)上进行了一些修复,然后意识到也应该应用它去“维护”。您应该将工作流基于合并或 rebase(或“git pull --rebase”)。

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

    在 git 中你也可以一次合并多个分支:所谓的 octopus merge。请注意,章鱼合并必须成功而不会发生冲突。不过它可能很有用。

    HTH。

    【讨论】:

    • +1 表示 rebase/cherry-picking 实际上“复制”了提交,因此失去了与原始提交的链接。
    • 我们以这种方式使用cherry-pick,专门用于将错误修复的提交(可能是非常小的功能)移动到现有的发布分支中以准备补丁。跨越多个提交的功能通常需要进入基于 master 的发布分支。
    • @foxxtrot:另一种解决方案是为错误修复创建一个单独的分支,基于显示此错误的最旧提交,并将其合并到“维护”和“主”中......虽然在这个如果您需要知道上述错误修复适用于两个分支。
    • @Jakub 创建和合并错误修复分支必不可少的两个命令:git blame 查找引入错误的提交,git branch --contains 确定合并分支的位置。在this post中有更详细的描述
    【解决方案3】:

    rebase(和cherry-pick)和merge 各有优缺点。我在这里主张merge,但两者都值得理解。 (在此处查找另一个经过充分论证的 answer 枚举案例,其中 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 个冲突。这仍然是很多工作,但不如尝试一次提交一次。

    【讨论】:

    • 实际上,理论上,Mallory 有可能通过创建具有相同 SHA1 但内容不同的提交来破坏您的存储库,但在实践中可能永远不会发生。 :)
    • 哈 :) 我的意思是“理论上可能性很小,你可以相信它不会发生”,但你说得对,它看起来很颠倒。
    • 你如何看待“合并 --squash”?
    • 9000 冲突?我会辞掉工作,成为养蜂人。
    • 3 个月独立于其他开发人员工作然后合并?他是在没有互联网的荒岛上吗?
    猜你喜欢
    • 2011-10-27
    • 2018-10-04
    • 1970-01-01
    • 1970-01-01
    • 2014-01-17
    • 2012-09-19
    • 2012-05-21
    • 2016-01-08
    • 1970-01-01
    相关资源
    最近更新 更多