假设我是一个 repo 的维护者,并且我想从贡献者那里获取更改,有一些可能的工作流程:
我从远程挑选每个提交(按顺序)。在这种情况下,git 将提交记录为与远程分支无关。我合并分支,拉入所有更改,并添加新的“冲突”提交(如果需要)。我单独合并来自远程分支的每个提交(再次按顺序),允许为每个提交记录冲突,而不是全部组合在一起。为了完整起见,您可以做一个变基(与樱桃选择选项相同?),但我的理解是这可能会导致贡献者混淆。也许这消除了选项1。
在情况 2 和 3 中,git 记录提交的分支历史记录,与 1 不同。
使用所描述的 cherry-pick
或 merge
方法之间的优缺点是什么? 我的理解是方法 2 是常态,但我觉得用单个“冲突”解决大型提交合并,不是最干净的解决方案。
rebase
(和 cherry-pick
)和 merge
都有其优点和缺点。我在这里主张 merge
,但两者都值得理解。 (在此处查找另一个有充分理由的 answer 列举了首选 rebase
的情况。)
出于几个原因,merge
优于 cherry-pick
和 rebase
。
稳健性。提交的 SHA1 标识符不仅可以识别它本身,还可以识别它之前的所有其他提交。这为您提供了一个保证,即给定 SHA1 的存储库状态在所有克隆中都是相同的。 (理论上)不可能有人做了看起来相同的更改,但实际上正在破坏或劫持您的存储库。您可以挑选个别更改,它们可能相同,但您不能保证。 (作为一个次要的次要问题,如果其他人再次在同一个提交中进行挑选,那么新挑选的提交将占用额外的空间,因为即使您的工作副本最终相同,它们也会出现在历史记录中。)使用。人们倾向于相当容易地理解合并工作流程。 rebase 往往被认为更高级。最好同时了解两者,但是不想成为版本控制专家的人(根据我的经验,其中包括许多非常擅长他们所做的事情但不想花费额外时间的同事)更容易时间刚刚合并。
即使使用大量合并工作流,rebase
和 cherry-pick
对于特定情况仍然有用:
合并的一个缺点是历史记录混乱。 rebase 可以防止一长串提交分散在您的历史记录中,就像您定期合并其他人的更改一样。这实际上是我使用它的主要目的。您要非常小心的是,永远不要对您与其他存储库共享的代码进行变基。一旦一个提交被推送,其他人可能已经在它之上进行了提交,并且变基充其量会导致上面讨论的那种重复。在最坏的情况下,您可能会得到一个非常混乱的存储库和细微的错误,这将需要您很长时间才能找出来。 cherry-pick 对于从您基本上决定丢弃的主题分支中抽取一小部分更改很有用,但意识到有几个有用的部分。
至于更喜欢合并多个更改而不是一个:它只是简单得多。一旦您开始拥有大量单个变更集,合并单个变更集可能会变得非常乏味。 git(以及 Mercurial 和 Bazaar)中的合并分辨率非常好。大多数时候,即使是长分支,您也不会遇到重大问题。我通常一次合并所有内容,只有当我遇到大量冲突时,我才会备份并重新运行合并。即便如此,我还是大块地做。作为一个非常真实的例子,我有一位同事需要合并 3 个月的更改,并且在 250000 行代码库中遇到了大约 9000 个冲突。我们要解决的问题是一次合并一个月的时间:冲突不会线性累积,并且分段执行会导致远远少于 9000 个冲突。这仍然是很多工作,但不如尝试一次提交一个提交。
在我看来,樱桃采摘应该保留在需要它的极少数情况下,例如,如果您直接在“主”分支(主干,主开发分支)上进行了一些修复,然后意识到它也应该应用于“维护” '。您应该将工作流基于合并或 rebase(或“git pull --rebase”)。
请记住,从 Git 的角度来看,cherry-picked 或 rebased 提交与原始提交不同(具有不同的 SHA-1 标识符),因此它与远程存储库中的提交不同。 (Rebase 通常可以处理这个问题,因为它检查补丁 id 即更改,而不是提交 id)。
同样在 git 中,您可以一次合并多个分支:所谓的章鱼合并。请注意,章鱼合并必须成功而不会发生冲突。尽管如此,它可能很有用。
HTH。
Rebase 和 Cherry-pick 是保持干净提交历史的唯一方法。避免使用合并,避免产生合并冲突。如果您正在使用 gerrit,请将一个项目设置为 Merge(如有必要),并将一个项目设置为樱桃挑选模式并尝试自己。
不定期副业成功案例分享