在使用 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 就已经被成功地重写了。