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

I cherry-pick each commit from the remote (in order). In this case git records the commit as unrelated to the remote branch. I merge the branch, pulling in all changes, and adding a new "conflict" commit (if needed). 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. For completeness, you could do a rebase (same as cherry-pick option?), however my understanding is that this can cause confusion for the contributor. Maybe that eliminates option 1.

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

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


改基(和择优选择)和合并都有各自的优点和缺点。我在这里主张合并,但两者都值得理解。(在这里可以找到另一个论证充分的答案,列举了rebase是首选的情况。)

出于几个原因,合并比选择和rebase更受欢迎。

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. 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 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.) Ease of use. People tend to understand the merge workflow fairly easily. rebase tends 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.

即使有大量合并的工作流,rebase和择优选择在特定情况下仍然有用:

One downside to merge is cluttered history. 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. 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. 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. 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.

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 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. 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. It was still a lot of work, but not as much as trying to do it one commit at a time.


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

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

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

HTH.


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