Git Cherry-pick vs Merge Workflow

cmc*_*nty 296 git merge cherry-pick

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

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

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

使用任何一种方法cherry-pickmerge描述的方法之间有什么优点和缺点?我的理解是方法2是常态,但我觉得用单个"冲突"合并解决大型提交并不是最干净的解决方案.

qua*_*ark 287

两者rebase(和cherry-pick)merge都有其优点和缺点.我在merge这里争论,但值得理解.(在这里查看一个备选的,有争议的答案,列举rebase优先考虑的案例.)

merge优于cherry-pickrebase一对夫妇的原因.

  1. 坚固.的提交SHA1标识符标识它不仅在其本身,而且相对于它前面的所有其他的提交.这可以保证给定SHA1的存储库状态在所有克隆中都是相同的.理论上(某些人)没有机会完成看起来像是同样的变化但实际上正在破坏或劫持您的存储库.你可以挑选个别的变化,它们可能是相同的,但你无法保证.(作为次要的次要问题,如果其他人在同一次提交中再次挑选,那么新的樱桃选择的提交会占用额外的空间,因为即使您的工作副本最终相同,它们也将出现在历史中.)
  2. 易于使用.人们倾向于merge相当容易地理解工作流程. rebase往往被认为更先进.最好同时理解这两者,但是那些不想成为版本控制专家的人(根据我的经验,他们包括许多同事,他们非常擅长他们的工作,但又不想花费额外的时间)更容易时间刚刚融合.

即使使用合并繁重的工作流程rebase,cherry-pick对于特定情况仍然有用:

  1. 一个缺点merge是混乱的历史. rebase防止一系列的提交在您的历史记录中分散,就像您定期合并其他人的更改一样.事实上,这是我使用它的主要目的.您想要非常小心的是,永远不要rebase编写您与其他存储库共享的代码.一旦提交了push其他人可能已提交的提交,并且重新定位将最多导致上面讨论的那种重复.在最坏的情况下,你最终可能会遇到一个非常混乱的存储库和微妙的错误,这将花费你很长时间才能发现.
  2. cherry-pick 对于从您基本上决定放弃的主题分支中抽取一小部分变化非常有用,但我们意识到有几个有用的部分.

至于将多个变化合并为一个:它只是简单得多.一旦你开始拥有很多变更集,就可以非常繁琐地完成各个变更集的合并.git(以及Mercurial和Bazaar中)的合并解析非常好.在大多数情况下,即使长分支合并也不会遇到重大问题.我通常会同时合并所有内容,只有我收到大量冲突时才会备份并重新运行合并的零碎内容.即便如此,我还是以大块的方式做到这一点.作为一个非常真实的例子,我有一位同事进行了3个月的合并更改,并在250000行代码库中获得了9000个冲突.我们要做的是修复一次合并一个月的价值:冲突不会线性增加,而且分段执行会导致远远少于9000个冲突.这仍然是很多工作,但并不像尝试一次提交一样多.

  • 9000次冲突?我辞掉了工作,成了一名养蜂人. (54认同)
  • 已经九千多了! (3认同)
  • 与其他开发人员隔离工作 3 个月然后合并?他是在没有网络的荒岛上吗? (3认同)

Jak*_*ski 93

在我看来,樱桃挑选应该保留在需要的罕见情况下,例如,如果你直接在'master'分支(主干,主开发分支)上做了一些修复,然后意识到它也应该应用于'maint ".您应该在合并或rebase(或"git pull --rebase")上建立工作流.

请记住,樱桃挑选的或重订提交是不同但从GIT中的(具有不同的SHA-1的标识符)比原来的点,所以它比在远程仓库提交不同.(Rebase通常可以处理这个,因为它检查补丁ID,即更改,而不是提交ID).

同样在git中你可以同时合并许多分支:所谓的章鱼合并.请注意,章鱼合并必须成功而不会发生冲突.不过它可能有用.

HTH.

  • 对于rebase/cherry-picking实际上"复制"提交并因此失去与原始提交的链接的点+1. (17认同)
  • @Jakub创建和合并bugfix分支必不可少的两个命令:`git blame`找到引入bug的提交,`git branch --contains`确定合并分支的位置.在[这篇文章]中有更详细的描述(http://gcbenison.wordpress.com/2012/01/17/git-bugfix-branches-choose-the-root-wisely/) (4认同)
  • @foxxtrot:另一个解决方案是为bug修复创建一个单独的分支,基于显示此错误的最旧提交,并将其合并为'maint'和'master'...虽然在这种情况下你需要知道所说的bugfix适用于两个分支机构. (3认同)