1.問題:
要上線了 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
2.解決方法:
有三個辦法:
1. 強制物理覆蓋重新提交一次
(此法暴力解決一切git問題...) (從master拉個新分支出來,物理拷貝feature分支代碼後提交, master再merge此分支)
2. master 分支reset 後 pull -f
(注意:一般master分支都有protect ,不讓回滾提交,要去gitlab上關閉此保護)
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
這樣代碼就都回來了
3.原理和拓展
回滾操作中: 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應該還會被引入。
參考:
https://blog.csdn.net/Fickle_actor/article/details/89097474
https://juejin.im/post/5b0e5adc6fb9a009d82e4f20