Git Cherry-pick vs 合并工作流

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1241720/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 06:50:40  来源:igfitidea点击:

Git Cherry-pick vs Merge Workflow

gitmergecherry-pick

提问by cmcginty

Assuming I am the maintainer of a repo, and I want to pull in changes from a contributor, there are a few possible workflows:

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

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

In both cases 2 and 3, git records the branch history of the commits, unlike 1.

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

What are the pro's and con's between using either cherry-pickor mergemethods described?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.

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

采纳答案by quark

Both rebase(and cherry-pick) and mergehave their advantages and disadvantages. I argue for mergehere, but it's worth understanding both. (Look here for an alternate, well-argued answerenumerating cases where rebaseis preferred.)

两者rebase(和cherry-pick) 和merge都有其优点和缺点。我在merge这里争论,但两者都值得理解。(在这里寻找一个替代的、论证充分的答案,列举了rebase首选的案例。)

mergeis preferred over cherry-pickand rebasefor a couple of reasons.

merge出于几个原因cherry-pick而被优先rebase考虑。

  1. Robustness. The SHA1 identifier of a commit identifies it not just in and of itself but also in relation toall other commits that precede it. This offers you a guarantee that the state of the repository at a given SHA1 is identical across all clones. There is (in theory) no chance that someone has done what looks like the same change but is actually corrupting or hiHymaning 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 mergeworkflow fairly easily. rebasetends to be considered more advanced. 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.
  1. 稳健性。的的SHA1标识提交识别它不仅在其本身,而且相对于它前面的所有其他的提交。这为您提供了一个保证,即给定 SHA1 的存储库状态在所有克隆中都是相同的。(理论上)不可能有人做了看似相同的更改,但实际上正在破坏或劫持您的存储库。您可以挑选个别更改,它们可能相同,但您不能保证。(作为一个次要的次要问题,如果其他人再次选择同一个提交,新的选择提交将占用额外的空间,因为即使您的工作副本最终相同,它们也会出现在历史记录中。)
  2. 易于使用。人们往往merge很容易理解工作流程。 rebase往往被认为更先进。最好同时了解两者,但是不想成为版本控制专家的人(根据我的经验,其中包括许多非常擅长他们所做的工作,但不想花额外时间的同事)有一个更容易时间刚刚融合。

Even with a merge-heavy workflow rebaseand cherry-pickare still useful for particular cases:

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

  1. One downside to mergeis cluttered history. rebaseprevents a long series of commits from being scattered about in your history, as they would be if you periodically merged in others' changes. That is in fact its main purpose as I use it. What you want to be verycareful of, is never to rebasecode that you have shared with other repositories. Once a commit is pushed someone else might have committed on top of it, and rebasing will at best cause the kind of duplication discussed above. 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-pickis 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.
  1. 一个缺点merge是杂乱的历史。 rebase防止一长串提交分散在您的历史记录中,就像您定期合并其他人的更改一样。这实际上是我使用它的主要目的。您要非常小心的是,永远不要rebase编写与其他存储库共享的代码。一旦提交被提交,push其他人可能已经在它之上提交,并且重新定位最多只会导致上面讨论的那种重复。最坏的情况是你最终会得到一个非常混乱的存储库和细微的错误,你需要很长时间才能发现。
  2. 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. You won't run into major problems merging even long branches most of the time. I generally merge everything all at once and only ifI 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. 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 farfewer than 9000 conflicts. It was still a lot of work, but not as much as trying to do it one commit at a time.

至于更喜欢合并多个更改而不是一个:它只是简单得多。一旦您开始拥有大量变更集,合并单个变更集会变得非常乏味。git(以及 Mercurial 和 Bazaar)中的合并解析非常好。大多数情况下,即使合并很长的分支,您也不会遇到重大问题。我通常一次合并所有内容,只有我遇到大量冲突时,我才会备份并逐步重新运行合并。即便如此,我还是大块地做。作为一个非常真实的例子,我有一个同事有 3 个月的时间进行合并,在 250000 行代码库中遇到了大约 9000 个冲突。我们所做的修复是一次进行一个月的合并:冲突不会线性累积,并且分片进行会导致很远少于 9000 个冲突。这仍然是很多工作,但没有尝试一次提交一次。

回答by Jakub Nar?bski

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'. 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 differentfrom the point of view of Git (has different SHA-1 identifier) than the original, so it is different than the commit in remote repository. (Rebase can usually deal with this, as it checks patch id i.e. the changes, not a commit id).

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

Also in git you can merge many branches at once: so called octopus merge. Note that octopus merge has to succeed without conflicts. Nevertheless it might be useful.

同样在 git 中,您可以一次合并多个分支:所谓的octopus merge。请注意,章鱼合并必须成功且无冲突。不过它可能有用。

HTH.

哈。

回答by Nagaraj Magadum

Rebase and Cherry-pick is the only way you can keep clean commit history. 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.

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