我有两个分支(我们称之为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重置为错误合并完成之前的点,然后挑选我们从那时起对其进行的更改,但由于已经有许多功能分支合并,因此很难(功能分支)包含错误的合并提交和恢复)。
答案 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并且不能进行有意义的合并。
有几种方法可以解决此问题。虽然可能有一些不需要重写历史的聪明的,但我能想到的两个确实需要重写历史记录。显然,所有重写历史的注意事项都适用于此。
第一种方法涉及从A的历史中删除合并。虽然此解决方案产生了更清晰的历史记录,但它可能对第一个产生更大的影响,特别是如果您在合并后分支了A。
(取自https://stackoverflow.com/questions/1338728/delete-commits-from-a-branch-in-git)
最简单的方法是使用交互式rebase。运行git rebase -i <sha>
(其中<sha>
是有问题的合并冲突的SHA)将允许您有选择地删除有问题的提交。只要您在使用时也删除了还原提交,并且此应该相对无痛。
另一种选择是创建一个新版本的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),将会有一些奇怪之处。具体来说,分支将从旧版本的分支创建,而不是更新的分支。
要解决此问题,对于此状态下的每个分支,您(或其他开发人员)将需要重新绑定到初始提交的新版本。如果这是一个问题,我可以在这里更具描述性。