一、背景:
??今天將一段代碼合入了master,上線的時候有問題,而不能很快解決掉蒙具,為了不影響其他同事合入master或將有問題的commit帶上線,因此我將我的commit revert掉了峰弹。
??同時店量,當天晚上的時候有同事剛好問我git revert后自己代碼消失的問題芜果,當時思考不清晰鞠呈,也比較少用revert,因此現在來復盤下右钾。
??commit提交流程示意圖如下:
其中A是有問題的commit蚁吝,R是revert的commit,M是master舀射,序號N代表master的流向
??如果我在commitA上rebase M3的代碼時窘茁,會發(fā)現代碼沒有變動,或者說在commitA中修改了部分內容再提交脆烟,A中的代碼合入master后還是消失了山林。
二、原因:
git合并歷史commit
??如果合并一個歷史commit邢羔,會以master的git歷史圖為準驼抹。
??原因是無論是merge還是rebase,都會先找到兩個分支的公共節(jié)拜鹤,再進行相應的合并操作框冀。但是歷史commit肯定是master的commit的父節(jié)點,所以兩個分支的公共節(jié)點必定就是歷史commit本身敏簿,所以rebase跟merge只會合并公共節(jié)點之后的commit明也,HEAD就只進行FastForward宣虾,最終跟master保持一致。
三温数、解決辦法
1. git revert VS git reset
??當想要修改有問題的遠程分支時绣硝,我們需要回退到沒有合入主分支的版本,該怎么做呢撑刺?
??git revert與git reset都能幫助我們解決問題域那,但是適用的場景不盡相同。
(1)git reset
??git reset的作用就在于重新設置HEAD猜煮,由于每次提交都會產生一個commit次员,我們用reset的時候可以制定我們要回退的歷史版本commit,如:
git reset --hard commitA
git reset --soft commitB
- hard 參數代表強重置王带,廢棄所有的提交淑蔚,因此會有代碼消失的風險,使用時需謹慎
- soft 參數代表弱重置愕撰,保留指定歷史commit之后所有的修改刹衫,并存放在暫存區(qū)(相當于git add .)
(2) git revert
??git revert實際就是將你merge到master的所有commit進行反向操作,并將所有的操作合并成一個commit搞挣,無論原本commit有多少带迟,都只會產生一個commit,命令如下:
git revert commitA
??操作完成之后再次合入到主分支即可"抵消"掉你原本merge的代碼
2. 解決revert帶來的代碼消失問題
??回退到原來版本后囱桨,如何將A的代碼中再次合入master呢?
??中心思想就是保留A代碼且需要一個新的分支仓犬。
??比較方便的做法是:在新的master開一個新branch,在新branch中再將revert掉你revert掉的代碼(有點像負負得正的意思)
git checkout -b new_branch
git revert commitR // git revert是會觸發(fā)生成一個commit的
// 此處bugfix
git revert:
- 優(yōu)點:能夠快速回滾代碼舍肠,并且可以保留revert記錄搀继,建議master分支回退代碼使用git revert
- 缺點:需要重新生成個新的分支并生成新的commit才能夠再次合入到master
3. 解決非master的回退
??我們可以使用git reset --soft來回退到指定的版本,并進行bugfix翠语,再推到遠程倉庫來修改提交歷史叽躯,但由于本地倉庫的HEAD與遠程倉庫的HEAD歷史產生了分叉,因此推到遠程分支的時候會報錯:
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
??為了解決歷史分叉問題肌括,并且保留現有新的提交点骑,我們可以強行將本地commit推到遠程倉庫,如:
git push origin --force branch
git push origin -f branch // -f是--force的縮寫
PS: !!! 使用 -f 的時候需要特別小心谍夭,因為你一旦將現有的提交強推上去了黑滴,可能會導致原有的有效代碼下掉,所以使用的時候切記當心慧库,必須清楚自己在干什么跷跪。
git reset:
- 優(yōu)點:能夠在同一個分支里面進行處理,分支合并操作次數較少
- 缺點:操作不會出現在歷史圖中齐板,開發(fā)分支回滾建議使用reset吵瞻。由于master是保護分支葛菇,不建議使用在master分支上
??具體使用哪個命令來處理建議結合具體場景分析,并沒有絕對的好壞橡羞。