一、什么是合并提交(Merge Commit)
合并提交是指通过 git merge 命令把一个分支合并到当前分支时产生的特殊提交。它有两个或多个父节点,通常用于整合分支开发成果。例如:
A---B---C---E (master)
\ /
D---F (feature)
合并 feature 到 master 后,会产生一个新的合并提交 E,它有两个父节点:C(master)和F(feature)。
二、为何撤销合并提交比较特殊
普通提交只有一个父节点,git revert <commit-hash> 可以直接反向应用。但合并提交有多个父节点,Git 不知道你要保留哪条分支的内容,所以需要额外指定"主分支"(即保留哪一条父分支的内容)。
三、撤销合并提交的命令及参数
1. 基本命令
bash
git revert -m <parent-number> <merge-commit-hash>
<merge-commit-hash>:你要撤销的合并提交的哈希值。-m <parent-number>:指定主分支的父节点编号(通常是1)。
2. 如何确定 parent-number?
- 如果你在
master分支上合并了feature,那么合并提交的第一个父节点(parent 1)通常是master,第二个父节点(parent 2)是feature。 - 一般撤销合并时,
-m 1表示保留当前分支(master)的内容,撤销被合并分支(feature)的变更。
3. 实例演示
假设你在 master 分支上执行了如下合并:
bash
git merge feature
# 产生了一个合并提交 hash 为 abcdef
后来发现合并有问题,需要撤销:
bash
git revert -m 1 abcdef
这会生成一个新的提交,内容是把合并分支的变动"反向应用",只保留主分支的内容。
四、撤销合并提交的注意事项
- 冲突处理:撤销合并提交时,可能会遇到冲突。需要按照 Git 的提示解决冲突,再提交。
- 只撤销合并,不影响主分支历史:revert 合并提交不会删除任何历史,只是新增一个"反向合并"的提交。
- 慎用 reset:如果合并提交已经推送到远程仓库,建议用 revert 而不是 reset,否则会破坏团队协作。
五、常见问题与解答
Q1. 如果我不确定 parent-number 应该是多少,怎么办?
可以用如下命令查看 merge commit 的父节点:
bash
git log -1 --pretty=raw <merge-commit-hash>
输出中会有 parent <hash> 字段,按顺序分别是 parent 1、parent 2......
Q2. 撤销合并提交后,能再次合并同一个分支吗?
如果你撤销了合并提交,Git 会认为你已经合并过该分支。此时再次合并可能会提示"Already up to date",需要用 --no-ff 或 --allow-unrelated-histories 之类参数。
Q3. 撤销合并提交和普通提交有什么区别?
- 普通提交只需要
git revert <commit-hash>。 - 合并提交必须指定主分支
-m <parent-number>,否则 Git 会报错。
六、总结
撤销合并提交的正确方式是:
bash
git revert -m <parent-number> <merge-commit-hash>
-m <parent-number>指定你要保留的父分支。- 适用于已推送远程仓库、团队协作场景。
- 不会破坏历史,安全可靠。