合并修补程序分支以开发重新引入旧更改

Merging hotfix branch to develop re-introduces old changes

我们一直在尝试 git 团队中的流程。我们基于 develop 分支创建发布分支。然后我们在release之后合并release分支到developmaster。到目前为止,我们已经发布了几个没有修补程序的版本。

现在,我们刚刚遇到了一个需要修补程序的事件(第一个修补程序)。所以我们基于 master 创建了修补程序分支。我们将 hotfix 分支合并到 master,一切都很好。然后我们尝试将修补程序分支合并到 develop,diff 显示旧的更改被重新引入到 develop。例如,有些文件本应删除,但在合并后重新添加到 develop 中。在合并之前,staging 和 master 是相同的(没有任何差异)。

知道是什么原因造成的吗?我想展示示例 history/graph,但由于合并,我们的历史非常混乱。

Any idea what is causing this?

当然是合并基础提交的选择。这个选择不是 你的: Git 根据提交图自动做出选择。这就是为什么 这个 步骤:

so we created hotfix branch based off of master

可能是创建错误(或者“根本原因”,如果你愿意的话)。

您可以查看 Git 认为哪些提交是 developmaster 的合并基础,使用:

git merge-base --all develop master

这将打印出一个或多个提交哈希 ID。1 如果它只打印 一个 哈希 ID——这是通常的情况——那么那个哈希 ID 就是合并基础提交的哈希 ID。如果它打印两个或更多,Git 将通过合并列出的提交来 构建 合并基础(无论如何 git-merge-recursive);这些情况很棘手。

请记住,git merge 完全是关于 组合更改 ,但 Git 根本不会 存储 更改. Git 存储 快照: 每个提交都保存每个文件的完整快照,作为一种时间冻结的存档,说这就是项目在这 (快照)时间。将快照变成变化的唯一方法是至少拍摄 两张 快照并进行比较,就像玩 Spot the Difference.

游戏一样

发现两个分支提示(masterdevelop)之间的差异是没有用的,因为将这些差异应用到一个分支提示只会产生另一个快照。 (在这种情况下,我们为什么还要为分支而烦恼?)所以这不是合并的工作方式。

相反,合并会找到 过去某处 的快照,回到 masterdevelop 分歧 [=85] 之前=].通过将 that 快照与 master 末尾的快照进行比较,Git 可以看到 master 中发生了什么变化。通过将 相同的 快照与 develop 末尾的快照进行比较,Git 可以看到 develop 中发生了什么变化。然后,Git可以合并这两组更改,以保留您的更改,但也添加他们的更改。

这个过程在算法上很简单——嗯,相对简单(尽管在实践中需要做很多工作,这就是为什么我们让 计算机 来做)。在某些情况下,它 简单,并且会产生错误的结果。你的情况似乎就是其中之一。

如果您找到引入 bug 本身的提交(过去的某个时间点,也许是遥远的过去)并创建一个分支,您可以在它之后立即修复该 bug简介,然后你可以将 this 分支合并到 master develop 中。从该分支的合并基础(使用 masterdevelop)到该分支的提示的更改将 只是修正 。从这个合并基础到 master 的尖端或 develop 的尖端的变化将是 发生的所有其他事情 。因此,将 this 分支合并到 masterdevelop 中通常会产生正确的结果,而不会引入其他不需要的更改。但这通常比为 master 制作一个修补程序分支更困难——有时 。所以选择权在你。

您可以考虑使用 git cherry-pick 将修补程序复制到 develop 分支。挑选樱桃有其自身的危险——例如,如果修补程序被证明有它自己的错误,现在你需要修复它两次——但它是商店里的另一种工具。 Git 是一家拥有大量工具的大商店。选择正确的锯子、锉刀、锤子、刨子、螺丝刀、钻头等,你会完成很多好事。选错了……好吧……


1如果历史不相关,它可能会打印 none,但在那种情况下,您会看到有关不相关历史的错误。