能撤销,但方法取决于所处环节:①冲突未解决用git merge --abort;②已提交未推送用git reset --hard orig_head;③已推送则必须用git revert -m1 。

能撤销,但方法完全取决于你卡在哪个环节:是否已提交、是否已推送、是否想保留历史。
合并冲突没解决完就发现错了
这是最轻量的情况。Git 还没生成合并提交,只是把冲突标记写进文件,索引和工作区处于“半合并”状态。
- 直接运行
git merge --abort,所有改动(包括冲突标记)都会被清理,HEAD、索引、工作区全部回到合并前一刻 - 这个命令只在
git merge启动后、git commit之前有效;一旦你执行了git commit,它就报错 “No merge in progress” - 不需要记哈希值,也不依赖
ORIG_HEAD,安全、快捷、无副作用
已经 commit 了合并,但还没 push 到远程
本地多了一个合并提交,但别人还没看到。这时 git reset 是首选,比 git revert 更干净。
- 用
git reset --hard ORIG_HEAD—— Git 在 merge 开始时自动保存了上一个 HEAD 的位置,比手动找HEAD~1更可靠(尤其当你中间还做了其他操作) - 如果
ORIG_HEAD被后续命令覆盖了,可以用git reflog查最近的 HEAD 移动记录,再git reset --hard到对应条目 -
--hard会丢弃所有未提交的修改,确认前先git status看一眼有没有漏掉的临时改动
合并提交已经推送到远程了
不能改历史,只能“加一笔”来抵消。这时候必须用 git revert,否则会破坏协作者的本地仓库。
- 运行
git revert -m 1 <merge-commit-hash></merge-commit-hash>,其中-m 1表示以当前分支(即被合并到的目标分支)为基准反向操作,撤销的是“从另一分支带来的更改” - 别用
HEAD直接代替哈希——万一你刚 revert 完又 merge 了一次,HEAD就不是那个合并提交了;稳妥做法是先git log --oneline -n 5确认 - revert 会产生一个新提交,需要
git push上去;如果远程拒绝(比如有别人新推了提交),得先git pull --rebase再 push
为什么 -m 1 和 -m 2 容易搞反
合并提交有两个父提交:HEAD^1 是当前分支的上一个提交(主干),HEAD^2 是被合并分支的 tip。撤销时选错,结果会完全相反。
- 假设你在
main上执行git merge feature,那-m 1撤销的是feature带来的所有变更,保留main原有内容 - 如果误用
-m 2,实际撤销的是main自己的更改,反而把feature的代码全留了下来——看起来像“没撤销” - 不确定时,先
git show <merge-commit-hash></merge-commit-hash>看 Parent 行顺序,或git log --graph --oneline main feature观察分叉结构











