Git撤销已Push的Merge
2024-10-23 18:07:51 8
复现场景
- 现有一个分支
master
- 基于
master
创建分支merge
master
正常commit & pushC
merge
正常commit & pushD
和E
- 将
merge
合并到master
, commit为M
A -- B -- C -- M (master)
\ /
D -- E (merge)
master
push
现在因为某些原因要撤销这次合并
操作方法
git log
找到合并的那次commit hash (名称一般为 Merge branch xxx)git revert -m 1 hash
保留创建分支后master的提交C
, 抛弃merge的提交D
和E
-m 1
表示保留master分支的更改 (保留第一个父提交 即合并前的主分支)-m 2
表示保留merge分支的更改 (保留第二个父提交 即被合并的分支)- git revert会再创建一个commit, 可以看到内容是撤销了
D
和E
- 将commit push, 这次撤销合并就完成了
- 假如第2步选择
-m 2
, 那么就可以看到master上的C
被撤销,D
和E
被保留
生产操作, 一般都是选择-m 1
, 即保留master
后续的commit.
因为master主干代码都是最稳定的
其他情况 一
- 假如
merge
的D
和E
后, 将master
的C
合并到merge
merge
再做了一次提交F
master
又做了一次提交G
- 最终将
merge
合并到master
这种是比较常见的场景.
需求开始时, 从master拉个新分支.
新分支写完后准备合并.
发现冲突了, 然后把master的代码合到新分支, 涉及冲突的, (可以)重新作为新分支的一个commit.
最终将新分支的代码合并到master上线
其他情况 二
- 假如
merge
的D
和E
后, 将master
的C
合并到merge
merge
再做了一次提交F
- 最终将
merge
合并到master
从git log
看, master
最新的commit是merge
的F
属于master的有ABC
, merge的DEF
方法一
这种可以先找到C
的hash
然后
git reset --hard <commit_hash_of_C>
然后强制推送到remote
git push origin master --force
缺点就是master不会有DEF
的相关记录了 (merge仍然有), 且会影响到其他人的合并
如果合并后刚push, 可以用reset再push (仓库允许强制push)
方法二
基于master的C
创建新分支, 再替换master
方法三
git rebase -i HEAD~7
交互性的选择保留或丢弃最近7个提交
方法四
一个一个revert