简体   繁体   English

Git Cherry-pick vs Merge Workflow

[英]Git Cherry-pick vs Merge Workflow

Assuming I am the maintainer of a repo, and I want to pull in changes from a contributor, there are a few possible workflows: 假设我是回购的维护者,并且我想从贡献者那里获取更改,那么有一些可能的工作流程:

  1. I cherry-pick each commit from the remote (in order). 我从远程中cherry-pick每个提交(按顺序)。 In this case git records the commit as unrelated to the remote branch. 在这种情况下,git将提交记录为与远程分支无关。
  2. I merge the branch, pulling in all changes, and adding a new "conflict" commit (if needed). merge分支,拉入所有更改,并添加新的“冲突”提交(如果需要)。
  3. I merge each commit from the remote branch individually (again in order), allowing conflicts to be recorded for each commit, instead of grouped all together as one. merge远程分支中的每个提交单独merge (再次按顺序),允许为每个提交记录冲突,而不是将所有提交组合为一个。
  4. For completeness, you could do a rebase (same as cherry-pick option?), however my understanding is that this can cause confusion for the contributor. 为了完整性,你可以做一个rebase (与cherry-pick选项相同?),但是我的理解是这会导致贡献者的混淆。 Maybe that eliminates option 1. 也许这消除了选项1。

In both cases 2 and 3, git records the branch history of the commits, unlike 1. 在情况2和3中,git记录了提交的分支历史记录,与1不同。

What are the pro's and con's between using either cherry-pick or merge methods described? 使用所描述的cherry-pickmerge方法之间有什么优点和缺点? My understanding is that method 2 is the norm, but I feel that resolving a large commit with a single "conflict" merge, is not the cleanest solution. 我的理解是方法2是常态,但我觉得用单个“冲突”合并解决大型提交并不是最干净的解决方案。

Both rebase (and cherry-pick ) and merge have their advantages and disadvantages. rebase (和cherry-pick )和merge都有其优点和缺点。 I argue for merge here, but it's worth understanding both. 我在这里争论merge ,但值得理解。 (Look here for an alternate, well-argued answer enumerating cases where rebase is preferred.) (在这里查看备选的,有争议的答案,列举优先使用rebase情况。)

merge is preferred over cherry-pick and rebase for a couple of reasons. 由于几个原因, merge优先于cherry-pickrebase

  1. Robustness . 坚固 The SHA1 identifier of a commit identifies it not just in and of itself but also in relation to all other commits that precede it. 的提交SHA1标识符标识它不仅在其本身,而且相对于它前面的所有其他的提交。 This offers you a guarantee that the state of the repository at a given SHA1 is identical across all clones. 这可以保证给定SHA1的存储库状态在所有克隆中都是相同的。 There is (in theory) no chance that someone has done what looks like the same change but is actually corrupting or hijacking your repository. 理论上(某些人)没有机会完成看起来像是同样的变化但实际上正在破坏或劫持您的存储库。 You can cherry-pick in individual changes and they are likely the same, but you have no guarantee. 你可以挑选个别的变化,它们可能是相同的,但你无法保证。 (As a minor secondary issue the new cherry-picked commits will take up extra space if someone else cherry-picks in the same commit again, as they will both be present in the history even if your working copies end up being identical.) (作为次要的次要问题,如果其他人在同一次提交中再次挑选,那么新的樱桃选择的提交将占用额外的空间,因为即使您的工作副本最终相同,它们也将出现在历史中。)
  2. Ease of use . 易于使用 People tend to understand the merge workflow fairly easily. 人们倾向于相当容易地理解merge工作流程。 rebase tends to be considered more advanced. rebase往往被认为更先进。 It's best to understand both, but people who do not want to be experts in version control (which in my experience has included many colleagues who are damn good at what they do, but don't want to spend the extra time) have an easier time just merging. 最好同时理解这两者,但是那些不想成为版本控制专家的人(根据我的经验,他们包括许多同事,他们非常擅长他们的工作,但又不想花费额外的时间)更容易时间刚刚融合。

Even with a merge-heavy workflow rebase and cherry-pick are still useful for particular cases: 即使使用合并繁重的工作流程, rebasecherry-pick仍然适用于特定情况:

  1. One downside to merge is cluttered history. merge一个缺点是混乱的历史。 rebase prevents a long series of commits from being scattered about in your history, as they would be if you periodically merged in others' changes. rebase阻止了一系列的提交在你的历史中分散,就像你定期合并其他人的更改一样。 That is in fact its main purpose as I use it. 事实上,这是我使用它的主要目的。 What you want to be very careful of, is never to rebase code that you have shared with other repositories. 您想要非常小心的是,永远不要重新rebase您与其他存储库共享的代码。 Once a commit is push ed someone else might have committed on top of it, and rebasing will at best cause the kind of duplication discussed above. 一旦提交被push其他人可能已经提交了它,并且重新定位将充其量导致上面讨论的那种重复。 At worst you can end up with a very confused repository and subtle errors it will take you a long time to ferret out. 在最坏的情况下,你最终可能会遇到一个非常混乱的存储库和微妙的错误,这将花费你很长时间才能发现。
  2. cherry-pick is useful for sampling out a small subset of changes from a topic branch you've basically decided to discard, but realized there are a couple of useful pieces on. cherry-pick非常适用于从您基本上决定丢弃的主题分支中抽取一小部分更改,但意识到有几个有用的部分。

As for preferring merging many changes over one: it's just a lot simpler. 至于将多个变化合并为一个:它只是简单得多。 It can get very tedious to do merges of individual changesets once you start having a lot of them. 一旦你开始拥有很多变更集,就可以非常繁琐地完成各个变更集的合并。 The merge resolution in git (and in Mercurial, and in Bazaar) is very very good. git(以及Mercurial和Bazaar中)的合并解析非常好。 You won't run into major problems merging even long branches most of the time. 在大多数情况下,即使长分支合并也不会遇到重大问题。 I generally merge everything all at once and only if I get a large number of conflicts do I back up and re-run the merge piecemeal. 我通常会同时合并所有内容,只有我收到大量冲突时才会备份并重新运行合并的零碎内容。 Even then I do it in large chunks. 即便如此,我还是以大块的方式做到这一点。 As a very real example I had a colleague who had 3 months worth of changes to merge, and got some 9000 conflicts in 250000 line code-base. 作为一个非常真实的例子,我有一位同事进行了3个月的合并更改,并在250000行代码库中获得了9000个冲突。 What we did to fix is do the merge one month's worth at a time: conflicts do not build up linearly, and doing it in pieces results in far fewer than 9000 conflicts. 我们要解决的问题是一次合并一个月的价值:冲突不会线性增加,并且分段执行会导致远远少于9000个冲突。 It was still a lot of work, but not as much as trying to do it one commit at a time. 这仍然是很多工作,但并不像尝试一次提交一样多。

In my opinion cherry-picking should be reserved for rare situations where it is required, for example if you did some fix on directly on 'master' branch (trunk, main development branch) and then realized that it should be applied also to 'maint'. 在我看来,樱桃挑选应该保留在需要的罕见情况下,例如,如果你直接在'master'分支(主干,主开发分支)上做了一些修复,然后意识到它也应该应用于'maint ”。 You should base workflow either on merge, or on rebase (or "git pull --rebase"). 您应该在合并或rebase(或“git pull --rebase”)上建立工作流。

Please remember that cherry-picked or rebased commit is different from the point of view of Git (has different SHA-1 identifier) than the original, so it is different than the commit in remote repository. 请记住,樱桃挑选的或重订提交是从视图GIT中的(具有不同的SHA-1的标识符)比原来的点不同 ,所以它比在远程仓库提交不同。 (Rebase can usually deal with this, as it checks patch id ie the changes, not a commit id). (Rebase通常可以处理这个,因为它检查补丁ID,即更改,而不是提交ID)。

Also in git you can merge many branches at once: so called octopus merge . 同样在git中你可以同时合并许多分支:所谓的章鱼合并 Note that octopus merge has to succeed without conflicts. 请注意,章鱼合并必须成功而不会发生冲突。 Nevertheless it might be useful. 不过它可能有用。

HTH. HTH。

Rebase and Cherry-pick is the only way you can keep clean commit history. Rebase和Cherry-pick是保持干净提交历史记录的唯一方法。 Avoid using merge and avoid creating merge conflict. 避免使用合并并避免创建合并冲突。 If you are using gerrit set one project to Merge if necessary and one project to cherry-pick mode and try yourself. 如果你正在使用gerrit,必要时将一个项目设置为Merge,将一个项目设置为cherry-pick模式并尝试自己。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM