git代碼回滾操做

昨天說到用git reset進行回滾操做,還有git revert的操做,它們的區別以下:git

git reset

git reset的做用是還原Index的狀態或修改本地分支HEAD的位置。這個命令適合用於從某個提交點開始,從新開新的分支。好比,若是某個提交以後的代碼咱們都不要了,就能夠在本地reset至指定commit,而後開一個新的branch繼續新的開發(原來分支在遠程上沒有發生任何變化的)。bash

使用git reset是不影響遠程分支的,一切都在本地發生。若是回退須要很快影響遠程分支的,應該使用git revert。spa

兩種狀況code

第一種狀況:只是在本地commit,尚未push到遠程分支,可經過如下命令實現:開發

git reset --soft|--mixed|--hard <commit_id>
git push 本地分支名稱 遠程分支名稱 --force

這裏的<commit_id>就是每次commit的SHA-1,能夠在git log裏查看到源碼

--mixed: 只是將git commit和index 信息回退到某個commit版本,仍會保留該commit_id以後提交的代碼
--soft: 只回退到commit信息到某個版本,不涉及index的回退,會保留源碼,若是還須要提交, 直接commit便可.
--hard: 源碼會回退到某個版本,commit和index 都會回退到某個版本. (這種方式會改變本地代碼倉庫源碼)it

固然有人在push代碼之後,也使用 reset --hard <commit_id> 回退代碼到某個版本以前,可是這樣會有一個問題, 線上的代碼還是回退以前的,線上commit, index都沒有變, 當你把本地代碼修改完提交的時候你會發現全是衝突.....ast

 

git revert

假如某些舊提交咱們不想要了,而又不肯經過 本身修改這些舊提交所產生的代碼,而後從新提交的方式 來完成,這個時候咱們就能夠把這項工做交給revert命令。class

Git Revert原理:根據你要回退的提交所作的改動作方向相反的改動,而後從新提交代碼,使代碼達到沒有這些舊提交所能達到的狀態。原理

若是對於git revert的回退策略還沒理解,這樣講也許你就能理解了:回退舊的提交必然會致使當前最新代碼發生變化,好比以前某個提交加了一行代碼,那麼回退就是在相同位置減一行代碼。Git不會真的把舊提交拋棄,若是直接拋棄,歷史記錄就追蹤不到了。所以,舊提交實際上是沒動的,Git只是根據舊提交反着作了一遍,這才致使最新的代碼發生了改變。只有把revert命令回退致使的改動從新提交,revert命令纔算真的完成並生效,不然效果只至關於修改了工做樹的文件而已。注意:revert以後須要push到遠程分支上其餘用戶才能看到回退發生的改動。

使用git revert會出現的問題

由於git revert是用新提交覆蓋舊提交,所以,被覆蓋的舊提交等於不會被採用了。若是兩個分支(假設是master和A分支)先合併再用revert回滾,以後又合併(A合併到master),就會發如今master分支上,A分支第一次合併以前的修改大部分不見了。這是由於從時間的發生順序來看,A分支第一次合併以前的修改發生在revert以前,revert發生在後,而 revert拋棄了A第一合併以前的修改,那麼再此合併Git就認爲你永遠拋棄了A第一次以前的修改。

要解決這個問題,須要把revert產生的提交再revert一次(至關於恢復以前的舊提交)。

 

二者區別

注意:git revert是用一次新的commit來回滾以前的commit,git reset是直接刪除指定的commit,看似達到的效果是同樣的,其實徹底不一樣。

第一:若是已經push到線上代碼庫, reset刪除指定commit之後, 你git push可能致使一大堆衝突,可是revert 不會;
第二:若是在往後現有分支和歷史分支須要合併的時候, reset 恢復部分的代碼依然會出如今歷史分支裏,但revert 方向提交的commit 並不會出如今歷史分支裏(注意!!!); 第三: reset 是在正常的commit歷史中, 刪除了指定的commit, 這時 HEAD 是向後移動了, 而 revert 是在正常的commit歷史中再commit一次, 只不過是反向提交, 他的 HEAD 是一直向前的。

相關文章
相關標籤/搜索