Git恢复后合并

时间:2015-12-15 14:39:38

标签: git version-control merge

我有两个分支(我们称之为A和B)。

A是我的常规开发分支,B是长期运行的功能分支 A经常合并到B中以使其保持最新状态,并且有一天B将合并到A中,但我们还没有达到这一点。

大约一周前,开发人员意外地将B合并到A中,然后通过运行git revert立即取消了合并。

从那时起,A有很多变化,包括将其他功能分支合并到其中。

今天,我试图像往常一样将A合并到B中,但现在我遇到了问题。

合并是从B中删除了B中添加的大量文件(可能是因为它们在运行git revert时从A中删除)并添加了从B中删除的大量文件(可能是因为它们是由git revert)。

它也没有在B中做很多改变。

  

我的问题是有没有办法彻底解决这个问题?   我对历史重新开放,因为我们有一个小团队,我们可以协调这个。

我尝试将A重置为错误合并完成之前的点,然后挑选我们从那时起对其进行的更改,但由于已经有许多功能分支合并,因此很难(功能分支)包含错误的合并提交和恢复)。

3 个答案:

答案 0 :(得分:2)

最简单的解决方案,假设您想要容忍丑陋的历史ID以恢复还原。

git revert SHA1-of-revert

后续合并应该可以正常工作。如果你想在以后相对容易的时候清理它,假设你已经基于坏的还原(包括未来的那些)合并了所有功能分支。

git rebase --interactive SHA1-of-revert~ 

然后删除恢复的行。这将为您提供完整的班轮历史。如果要保留要素分支的合并,请添加--preserve-merges选项。

git rebase --interactive --preserve-merges SHA1-of-revert~

答案 1 :(得分:1)

我会尝试将分支B重新分支到分支A

在此步骤之前,保存您的位置可能是个好主意,以防您以后意识到出现了错误。所以,首先创建一个临时分支:

git branch savePoint

在你做rebase之前,我强烈建议你阅读一两篇关于变基的教程,例如this one

现在,运行此命令:

git rebase A

这将重新播放分支B顶部的A上的每个提交(从A上不存在的最早的提交开始)。

如果检测到代码冲突,请遵循Git提供的说明,它将类似于解决合并冲突。

当rebase完成并且您已经测试并验证了一些正常工作后,您需要强制推送您的更改,因此请在您的推送命令中使用-f选项。

最终结果就好像有人在分叉B之后立即在A上编写了所有代码。使用gitk之类的工具可视化树,以确保您理解这一点。

如果您觉得rebase以某种方式出错,只需重置回保存点:

git reset --hard savePoint

一个非常重要的注意事项:此rebase将清理您的历史记录,但是从分支B撤出的其他人现在将“不同步”。这意味着B的新远程提示无法访问B分支的提示。

他们可以与新重写的B分支“同步”:

git checkout B
git fetch
git rebase origin/B

答案 2 :(得分:1)

所以问题是即使你恢复了合并提交,Git也不会以有意义的方式跟踪它(为了将来的合并)。所以基本上现在Git认为A中有大部分B并且不能进行有意义的合并。

有几种方法可以解决此问题。虽然可能有一些不需要重写历史的聪明的,但我能想到的两个确实需要重写历史记录。显然,所有重写历史的注意事项都适用于此。

方法1:删除A

上的合并

第一种方法涉及从A的历史中删除合并。虽然此解决方案产生了更清晰的历史记录,但它可能对第一个产生更大的影响,特别是如果您在合并后分支了A。

(取自https://stackoverflow.com/questions/1338728/delete-commits-from-a-branch-in-git)

最简单的方法是使用交互式rebase。运行git rebase -i <sha>(其中<sha>是有问题的合并冲突的SHA)将允许您有选择地删除有问题的提交。只要您在使用时也删除了还原提交,并且此应该相对无痛。

方法2:用新分支替换B

另一种选择是创建一个新版本的B,以便git分别跟踪它们。让我们假设您的树开头是这样的:

E -- F -- G -- H (branch A)
  \
   \
     I -- J -- K (branch B)

我相信以下行会解决问题:

git rebase -f <sha of E> B

这应创建一个尚未合并到A中的B副本。

注意:对于上述任何一种方法,如果在错误合并后的任何时刻分支更改的分支(A或B,取决于方法1或2),将会有一些奇怪之处。具体来说,分支将从旧版本的分支创建,而不是更新的分支。

要解决此问题,对于此状态下的每个分支,您(或其他开发人员)将需要重新绑定到初始提交的新版本。如果这是一个问题,我可以在这里更具描述性。