使用合并冲突重新设置基础:如何撤消?
Posted
技术标签:
【中文标题】使用合并冲突重新设置基础:如何撤消?【英文标题】:Rebased with merge conflicts: How to undo? 【发布时间】:2019-03-24 03:08:50 【问题描述】:我正在研究一个月前从 master 分支出来的功能分支 B。随着其他新功能的出现,主分支不断更新。
这是 master 分支现在的样子:
1 -> 2 -> 3 -> 4 -> 5 -> 6 ->7
当我第一次分支时,它看起来像这样:
1 -> 2 -> 3
这就是我的功能分支 (B) 现在的样子:
x -> y -> z
现在我已准备好将我的新功能推送到 master,建议我先从 master 变基,然后创建 PR。
在执行git rebase
时,我的分支遇到了与几个文件的合并冲突。我以为我会保留传入的更改,并且变基将正常进行。但是,我解决了冲突,将整个“REBASE MASTER”步骤转换为一种“MERGE MASTER”。又名:它将已经合并到 master 中的提交应用到我的功能分支中,而不是我最初打算对 git rebase
做的事情。
这就是我的功能分支现在的样子:
x -> 4 -> 5 -> 6 -> y -> 7 -> z
这是我想要实现的(但没有实现):
1 -> 2 -> 3 -> 4 -> 5 -> 6 ->7 -> x -> y -> z
我怎么回去?这已经被推送到远程分支,所以我不能简单地删除我的本地分支并再次从原点获取。
我能想到的一种方法是再次从 master 分支出来,并创建一个功能分支 C。然后,从 B 到 C 的cherry-pick 提交。一旦我确定 C 是 B 的完整副本(并且只包含我想要的提交),我可以删除 B。我错过了什么吗?还是有更好/更快的方法?
【问题讨论】:
你的功能分支确实不看起来像我对master
的简单变基所期望的那样。我这样说是因为来自两个分支的提交以一种看似随机的方式散布在一起。以下是 rebase 后的样子:1 -> 2 -> 3 -> 4 -> 5 -> 6 ->7 -> x -> y -> z
...也许您应该给出恰好使您处于这种状态的 确切步骤。
您希望rebase
做什么?你还知道你的“旧”z 的提交 id 吗?如果是,您可以查看它,它没有被删除。
@TimBiegeleisen 这正是我所期望的 git rebase 最终结果。但是由于合并冲突和我手动解决它们,我最终得到了那个历史记录。
@Lux 您能否详细说明如何帮助我撤消此操作?
如果您已经提交并推送,那么您无法真正撤消此操作。您可以尝试使用git revert
。很可能,您在 rebase 期间犯了一些严重错误,而不仅仅是解决合并冲突,这是相当普遍和正常的事情。
【参考方案1】:
(首先,以防万一,使用git rebase --abort
中止任何正在进行的rebase)
你是唯一一个在这个特性分支上工作的人吗? (我猜是这样,我会在下面假设它)
PR 已经被接受/合并到 master 了吗?
如果不是,那么这是一个非常可撤销的情况。 (这可能是 Lux 在 cmets 中暗示的)
首先,找到您需要恢复的提交哈希(在您的示例中为z
)。为此,您可以检查您的分支的 reflog(或者如果可用,可以从您最近的命令输出中选择它)。
然后将本地分支 B 恢复到旧引用(在变基之前)并再次将其推送到远程(使用 --force
,因为 git 会抱怨这不是线性历史)。
git branch -f B <commit_hash_of_z>
git push -f origin B
现在你可以重做你的 rebase 并尝试找出它上次横盘的位置。
【讨论】:
【参考方案2】:有一个选项可以恢复签到,这本身就是单独的签到。
但我建议您仔细阅读并阅读。
https://www.atlassian.com/git/tutorials/undoing-changes/git-revert
我也希望你了解“在 B 上重新设置 A”和“将 A 与 B 合并”的区别
如果你正在做rebase,我会建议你在本地更新master的来源。(这是我保持东西位管理的技巧,我不知道它是否是标准的)
【讨论】:
对不起,我错过了一段,(从手机阅读)。正如您所说,您已经提交了它,唯一的解决方案似乎是采用旧的基础和樱桃挑选,然后签入所需的更改。我知道这很头疼。 此外,我们遵循的是,如果最终代码集中有一些问题,我们会使用“fix-A-on-B..”再次签入,对我们来说重要的是代码的形状不是分支以上是关于使用合并冲突重新设置基础:如何撤消?的主要内容,如果未能解决你的问题,请参考以下文章