问题描述
要上线了 master 分支 merge feature分支,后上线
git checkout master
git merge origin/feature
此时发现feature分支代码有问题, master 就revert此次merge (紧急回滚上线)
(野路子操作,正规线上回滚操作流程 应该是每次上线打个tag,想回滚直接部署前一个tag)
git revert < commit id > -m 1
在feature 分支把问题修复后,master分支再次merge feature分支
git merge origin/feature
问题出现了 第一次merge的代码在master里”消失了”,再怎么merge 都无法merge上
原因: 因为git第一次merge此分支了, revert 只是在此分支上提交了一次”反向修改”(相当于 新的commit). 这merge和revert 这两次都相当于commit
解决方法:
1. 强制物理覆盖重新提交一次
此法暴力解决一切git问题…
操作方法: 从master拉个新分支出来,物理拷贝feature分支代码后提交, master再merge此分支
2. master 分支reset 后 pull -f
注意:一般master分支都有protect ,不让回滚提交,要去gitlab上关闭此保护 (所以此法适用于非master分支)
git checkout master
# 把master回滚merge之前的状态
git reset head^ --hard
(或 git reset --head "<>")
# 强制推上去
git push -f
# 重新merge feature后再推远程即可
git merge feature
git push
git reset head^ —hard : head^表示回滚到上一个提交版本 —head 本地代码会被覆盖
3. 对 revert 的那次提交记录再次进行revert (官方推荐方法)
见: https://stackoverflow.com/questions/19379034/force-merge-after-reverting-merge-commit-int-git
具体操作方法:
git checkout master
# 从master拉一个新分支 revert_tmp
git checkout -b revert_tmp
# 找到 revert 的那条提交记录,注意了,revert 相关的会有两条记录,第一条是 revert,第二条是 revert 后 merge 的记录,这里取第一条
# 用revert_tmp分支revert之前的revert
git revert <版本号>
# 再用master分支合并此分支代码推到远程即可
git checkout master
git merge revert_tmp
git push
这样代码就都回来了
当然也可以直接在master 上revert 之前revert的分支即可(不用新拉分支), 但是注意解决好冲突
原理和拓展
回滚操作中: git revert 和 git reset的区别:
- git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commit。
- git reset 是把HEAD向后移动了一下,而git revert是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容。
- 在回滚这一操作上看,效果差不多。但是在日后继续merge以前的老版本时有区别。因为git revert是用一次逆向的commit“中和”之前的提交,因此日后合并老的branch时,导致这部分改变不会再次出现,但是git reset是之间把某些commit在某个branch上删除,因而和老的branch再次merge时,这些被回滚的commit应该还会被引入。