在 git 中重新合并一个分支

git

在使用 git 管理代码的过程中,有时候一不小心合并错了分支,或者对之前的合并不满意,想重新合并一次,这时候要怎么办呢?

分两种情况

代码还没有被推送到远程仓库

这种情况最简单,直接硬重置到合并前,然后重新 merge 需要合并的提交就好。

$ git reset --hard ba45ae7ef2993c4adf66b3b531f2ec1cdb54bde3
HEAD 现在位于 ba45ae7 课前提醒 50%

$ git merge 41f6e855a87bd892e081adb6d9dbfc468257d5fa
自动合并 gradle.properties
冲突(内容):合并冲突于 gradle.properties
自动合并 app/src/main/res/values/dimens.xml
自动合并 app/src/main/AndroidManifest.xml
冲突(内容):合并冲突于 app/src/main/AndroidManifest.xml
自动合并失败,修正冲突然后提交修正的结果。

然后就可以重新进行 merge 了。

代码已经被推送到远程仓库

这种情况下,使用硬重置似乎就不是很厚道了,毕竟强制推送常常会引发一堆意想不到的事情。

然而git revert是不能直接 revert 一个合并提交的,会产生以下错误:

$ git revert 0586e6cb594524194f0e3694bec325a084b64dee
error: 提交 0586e6cb594524194f0e3694bec325a084b64dee 是一个合并提交但未提供 选项。
fatal: 还原失败

要想 revert 一个合并提交,必须指明想要 revert 到哪里,git-scm 的一篇官方博客 上给出了解决方案,需要 revert 两次,但是试了试似乎并没有什么效果(貌似只支持 revert 在git pull过程中产生的合并)。

最终还是用git reset搞定,首先 checkout 到一个临时分支,然后做与第一种情况相同的事情

$ git checkout -b re-merge
切换到一个新分支 're-merge'

$ git reset --hard ba45ae7ef2993c4adf66b3b531f2ec1cdb54bde3
HEAD 现在位于 ba45ae7 课前提醒 50%

$ git merge 41f6e855a87bd892e081adb6d9dbfc468257d5fa
自动合并 gradle.properties
冲突(内容):合并冲突于 gradle.properties
自动合并 app/src/main/res/values/dimens.xml
自动合并 app/src/main/AndroidManifest.xml
冲突(内容):合并冲突于 app/src/main/AndroidManifest.xml
自动合并失败,修正冲突然后提交修正的结果。

然后重新进行合并并提交,回到刚才的分支

# 重新进行合并

$ git commit -m "re-merge"
[re-merge ec7afc5] re-merge

$ git checkout develop
切换到分支 'develop'

然后将当前分支与刚才的临时分支合并

$ git merge re-merge
自动合并 gradle.properties
自动合并 app/src/main/AndroidManifest.xml
冲突(内容):合并冲突于 app/src/main/AndroidManifest.xml
自动合并失败,修正冲突然后提交修正的结果。

刚解决的冲突看起来又出现了,由于我们已经在临时分支里解决了所有冲突,这次直接把冲突的文件从刚才的临时分支里 checkout 出来就好了

$ git checkout re-merge app/src/main/AndroidManifest.xml

$ git commit -m "re-merge"
[develop 4f373a7] re-merge

到此,之前那次不令人满意的 merge 就已经被成功地重写了。