2

我在 Git 中有一个我无法解决的问题。我已经搜索了类似的案例,但我无法找到适合我情况的好的解决方案。

我基本上有 2 个分支,master 和 bugfix。错误修复是在我们完成发布时从 master 派生的。每次我们在 bugfix 中修复某些内容并进行 bugfix 发布时,我们都需要将其合并到 master 中。Master 包含新功能(当然不应该合并到错误修复中)。碰巧有人错误地将master与bugfix合并。

This is what happened:

 master: x1---x2
                \
 bugfix: y1--y2--M

where M is the merge between bugfix and master

一个解决方案是恢复我使用“git revert -m 1 M”(M 是来自合并的 SHA)所做的合并,如此处所述。我做了一个还原,因为我们已经在 bugfix 分支中进行了其他我们不想丢失的更改,这对于 bugfix 分支来说效果很好。

Current state:

 master: x1--x2------------x---x

 bugfix: y1--x1--y2--x2--M--y--y--R1

where R1 is the revert of M

当我们需要在 master 中合并 bugfix 分支时,问题就会出现。如我发布的链接中所述,revert 修复了代码更改但不修复历史记录,这意味着当我在 master 中合并 bugfix 时,revert 将生效并从 master(x1 和 x2)中删除更改。我能做的是在我将它合并到master之前恢复bugfix中的revert。

Solution:

 master: x1--x2------------x---x--------M
                                       /
 bugfix: y1--x1--y2--x2--M--y--y--R1--R2

where R2 is the revert of R1

这可行,但不是最终解决方案,因为每次我们进行合并时,我们都需要执行“revert of the revert”。几天来,我一直在寻找永久解决方案,似乎唯一的选择是从错误修复分支的历史记录中删除主提交(x1 和 x2)。但是这里使用 x1 和 x2 只是作为示例,实际上我们有更多的提交,并且剖析 bugfix 分支的历史非常困难且容易出错。我确信 Git 可以帮助我做到这一点,但我不知道怎么做。

任何想法都会非常有帮助。

4

3 回答 3

2

我个人建议重写历史(参见Useless的答案)并告诉你的团队。但这需要每个人都具备一定程度的 git 知识。如果重写方法对您来说风险太大,这里有一个替代方案:

发生了什么

每当您合并AB时,git 都会添加所有可以从A但不能到达的提交/B更改B。你的回复就是其中之一。正如您所注意到的,如果不重写,您将无能为力。

解决方案

您将不得不将还原合并到主文件中。由于您希望将恢复的内容保留在 master 中,因此您还需要在 master 上撤消该恢复(=可从 master 访问)。实现这一目标的最佳方法是使用以下命令:

git checkout -b bugfix-revert bugfix
git revert R1
git checkout master
git merge bugfix-revert
git branch -d bugfix-revert

在这些命令之后,每个分支都将处于您想要的状态,并且您可以从现在开始再次合并错误修复。您的历史记录将如下所示:

 [master] x1---x2----------------------H
                 \                    /
 [bugfix-revert]  \                  M''
                   \                /
 [bugfix] y1--y2----M--y3--y4--M'--y5

如您所见,mastercontains M',但其更改不在 中H,因为M''撤消了这些。M'永远不会应用于master,因为它已经包含它。状态bugfix没有改变,也不必改变。

于 2013-05-23T13:59:11.817 回答
1

为什么不首先创建一个没有错误合并的新错误修复分支?不过,您需要与每个人协调切换分支,以确保不会丢失任何提交

所以你有了:

 [master] x1---x2
                 \
 [bugfix]  y1--y2--M--y3--y4--M'

M'的回归在哪里M)。但是,您可以创建一个新分支:

$ git branch bugfix-fix y4

 [master] x1---x2
                 \
 [bugfix]  y1--y2--M--y3--y4--M'
                          ^^
                     [bugfix-fix]

将其从有问题的合并和还原中分离出来

$ git rebase --onto y2 M bugfix-fix

 [master] x1---x2
                 \
 [bugfix]  y1--y2--M--y3--y4--M'
                 \
 [bugfix-fix]     y3'--y4'

然后一旦你验证了你需要的一切都在bugfix-fix,你可以重命名两个分支

$ git branch -m bugfix bugfix-broken
$ git branch -m bugfix-fix bugfix

(你需要强行推动它,只要你与可能检查过它的每个人协调,这是安全的)。

于 2013-05-23T13:42:09.600 回答
-1

您的解决方案是正确的......您需要“还原还原”,然后与您的错误修复分支进行另一次合并(以提取在第一次错误合并后完成的任何错误修复提交),正如您所展示的那样。这将从您的 y1 和 y2 提交中恢复修复,保持您的历史记录正确并提取在第一个错误合并点之后执行的更新更改。

您无需担心未来的合并,因为最后一个合并点是历史中 git 尝试进行合并的地方,而不是之前的任何内容(与您需要执行“revert of the revert”的确切原因相同')...


不知道您为什么说这会使错误修复处于损坏状态。以下工作正常。您可以根据需要继续在错误修复分支上工作,而不必担心必须再恢复任何内容(除非您显然再次做同样的事情......)。如果您将来需要再次与 master 合并,您可以毫无问题(不需要做任何特别的事情),因为 git 知道历史,并且只会从两个分支最后共同的点查找合并问题/冲突(这最后合并)。

https://github.com/g19fanatic/stackoverflow-16713251-496405

gitk 示例


这是一个与 Linus 的链接,描述了这个问题,并提出了我上面提出的解决方案作为纠正它的一种可能方法......

于 2013-05-23T11:54:45.043 回答