Git-使用樱桃采摘时分支之间的差异 如何通过合并来修复错误

问题描述

我们当前正在使用Azure DevOps。我们有一个根据版本不同而有多个分支的存储库,即分支 version 1 version 2 version 3

如果在版本1 中修复了错误,那么我们希望在版本2 版本3 中具有相同的修复。但是版本1 不是版本2 的子集,因此我们不能使用merge命令。 版本2 版本3 之间相同。因此,我们使用“摘樱桃”来解决问题。

存在未在所有版本中实施修补程序的风险。我想查看在版本1 中完成的提交,而不是在版本3 中完成的提交。不包括已经摘录到版本3 的提交。有没有办法在分支之间进行区分,该分支还可以处理经过精心挑选的提交?

解决方法

我和其他人会认为,选择樱桃是解决眼前问题的错误工具:请参阅Raymond Chen博客系列文章,标题为Stop cherry-picking,start merging。与Lasse V. Karelsen comments一样,精心挑选的提交不捆绑在一起。合并提交 捆绑在一起,因此合并可提供更多指示,表明如果修复未完成,则可能需要进行其他合并。

在阅读完以下链接的博客文章或我极其有限的摘要并更改了总体工作流程后,您将创建一个分支,用于修复某些特定的错误并在那里进行修复工作。然后,您可以将此分支合并到错误的每个候选发布分支中。如果修正不足,您将向修正分支添加更多提交,并且需要将其重新合并到每个候选发布版本中。根据您的错误跟踪系统,您可能希望让 Git 查找将fix分支的上一个技巧提交合并到的分支。为此,您可以使用git branch --merged(或者,如果您要构建自己的工具,git for-each-ref,它是git branch和{{ 1}})。因此,使用合并方法可以为您提供更好的工具。

如何通过合并来修复错误

请注意,这是我对博客文章的摘要;还有很多东西要学习。我仅将其包括在内是为了讨论StackOverflow帖子的基本规则,因为博客链接会随着时间的推移而发生变化并且需要维护,所以这些内容必须独立(至少对于SO系统本身而言)。

随着时间的流逝,软件中发生的事情是我们编写的代码中的错误不会立即显示出来。当我们使用良好的版本控制系统时,这可以让我们 trace 找出错误的出处。如果将其绘制为简化的Git提交历史记录图,则它看起来像这样:

git tag

在这里,提交 o--...--A <-- release-1 / / o--...--B <-- release-2 / / ...--o--o--X--o--:--:--...--C <-- release-3 \ \ \ o--...--D <-- release-4 \ o--...--E <-- release-5 是其中包含实际 bug 的提交。从图中可以看出,该错误现在感染了五个版本。

我们过去无法修复该错误,因此,我们经常做的是天真地修复其中一个发行版中的错误:

X

其中 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 时解决问题发生的地方,该怎么办?好吧,有了版本控制系统,我们可以 1

我们直接签出历史​​记录提交X,然后在其上附加一个新的分支名称-很难绘制我绘制图形的方式。这是一个尝试:

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 的提交链不适当或不正确,我们可以添加更多的提交{ {1}}等修复它们,然后重新进行每个合并。

无论如何,这不是灵丹妙药,但它比cherry-pick方法要好得多,因为它将修复程序锁定到错误并在Git提交图中留下了痕迹。 Git提交图 是项目的历史记录,因此这些痕迹表明这是一个重要的修复程序,已被带回多个版本。请注意,该图本身相当粗糙且机械,因此包含好的提交消息非常重要。 F1-F2-F3-F4默认情况下制作的效果不佳,但确实具有可预测地形成的优点,因此可以机械搜索。


1 还有其他一些条件也适用:拥有VCS是必要的,但还不够。