我和其他人会争辩说,摘樱桃是解决手头问题的错误工具:请参阅 Raymond Chen 标题为 Stop cherry-picking, start merging 的博客系列文章。与Lasse V. Karelsen comments 一样,精心挑选的提交并没有捆绑在一起。合并提交捆绑在一起,因此合并提供了更多指示,表明如果修复未完成,可能需要额外的合并。
在您阅读了下面链接的博客文章或我非常有限的摘要并更改了您的总体总体工作流程后,您将创建一个分支来修复一些特定的错误并在那里进行修复工作。然后,您将把这个分支合并到每个 具有 错误的发布候选分支。如果修复被证明是不充分的,您将向修复分支添加更多提交,并且需要将其重新合并到每个候选版本中。根据您的错误跟踪系统,您可能希望 Git 找到合并了之前修复分支的提示提交的分支。为此,您可以使用git branch --merged(或者,如果您想构建自己的工具,git for-each-ref,这是git branch 和git tag 的一些瓷器部件的管道版本)。因此,使用合并方法可以为您提供更好的工具。
如何通过合并修复bug
请注意,这是我对博文的总结;那里还有很多东西要学。我包含此内容只是为了涵盖 StackOverflow 帖子的基本规则,这些帖子需要自包含(至少对于 SO 系统本身),因为博客链接会随着时间而变化并需要维护。
随着时间的推移,软件中会发生的情况是,我们编写的代码中的错误不会立即显现出来。当我们使用良好的版本控制系统时,这使我们能够跟踪错误到它们的起源点。如果我们把它画成一个简化的 Git 提交历史图,它最终看起来像这样:
o--...--A <-- release-1
/
/ o--...--B <-- release-2
/ /
...--o--o--X--o--:--:--...--C <-- release-3
\ \
\ o--...--D <-- release-4
\
o--...--E <-- release-5
这里,commit X 是其中包含实际 bug 的那个。从图中我们可以看出,这个错误现在感染了五个版本。
我们无法修复过去的错误,所以我们经常做的——天真地——修复其中一个版本的错误:
o--...--A--F1 <-- release-1
/
/ o--...--B <-- release-2
/ /
...--o--o--X--o--:--:--...--C <-- release-3
\ \
\ o--...--D <-- release-4
\
o--...--E <-- release-5
其中F1 是修复错误的提交。但现在我们必须将F1 复制到每个版本:
o--...--A--F1 <-- release-1
/
/ o--...--B--F2 <-- release-2
/ /
...--o--o--X--o--:--:--...--C--F3 <-- release-3
\ \
\ o--...--D--F4 <-- release-4
\
o--...--E--F5 <-- release-5
如果解决方法简单明了,无需重新审视,从根本上来说没有任何问题。我们最终会提交 5 次提交,这是实际解决问题所需的最低要求。
但是,如果修复是微妙而复杂的,或者引入了必须稍后解决的性能问题,或者可能需要额外的工作怎么办?稍后,当我们提出另一个提交或一系列提交来修复问题时,我们将不得不返回并单独修改每个分支。如果我们可以及时回到我们的旧代码并在提交X 处解决问题发生的位置,会怎样?好吧,有了版本控制系统,我们可以。1
我们直接检查历史提交 X,然后为其附加一个新的分支名称 - 有点难以绘制我一直在绘制图表的方式。这是一个尝试:
o--...--A <-- release-1
/
/ o--...--B <-- release-2
/ /
...--o--o--X--o--:--:--...--C <-- release-3
. \ \
. \ o--...--D <-- release-4
. \
. o--...--E <-- release-5
.
. <-- fix-bug-where-it-cropped-up
现在,在这一点上,我们进行修复提交:
o--...--A <-- release-1
/
/ o--...--B <-- release-2
/ /
...--o--o--X--o--:--:--...--C <-- release-3
. \ \
. \ o--...--D <-- release-4
. \
. o--...--E <-- release-5
.
.--F1--F2--F3--F4 <-- fix-bug-where-it-cropped-up
这个分支的尖端——此时提交F4——现在可以合并回每个现有的发布或开发分支。每次合并都会生成一个新的合并提交,因此我们最终得到的总提交数比樱桃采摘很好的超级简单案例要多。但这些提交实际上记录合并。这是进入release-5的那个:
o--...--A <-- release-1
/
/ o--...--B <-- release-2
/ /
...--o--o--X--o--:--:--...--C <-- release-3
. \ \
. \ o--...--D <-- release-4
. \
. o--...--E-----M5 <-- release-5
. /
.--F1--F2--F3--F4 <-- fix-bug-where-it-cropped-up
(我不会尝试绘制其他合并,因为图表很快就会变得非常混乱。)如果我们稍后发现F1-F2-F3-F4 提交链不充分或不正确,我们可以添加更多提交F5等来修复它们,然后重新进行每个合并。
无论如何,这不是万能药,但它比cherry-pick 方法更好,因为它将修复固定到错误并在Git 提交图中留下痕迹。 Git 提交图是项目的历史,所以这些痕迹表明这是一个重要的修复,带回多个版本。请注意,图表本身相当粗糙和机械,因此包含好的提交消息很重要。 git merge 默认生成的不是很好,但确实具有可预测形成的优势,因此可以进行机械搜索。
1还有其他适用的条件:拥有 VCS 是必要的,但还不够。