git(五)回退reset與revert

前言

        我們在使用git作爲代碼的分佈式版本控制工具時,稍有不慎可能會遇到合併錯代碼分支或者提交錯誤代碼分支的情況,而我們也有reset和revert兩種方式幫我們彌補錯誤,而reset和revert都有着不同的使用場景。下面就以我的視角來分享一下reset、revert的具體原理與使用場景,還有在我們之前的一次合錯master分支後使用git push -f 強推方式的不錯的解決方案。

代碼回退

       git 中的resetrevert都可以對當前的代碼進行回退,兩種的原理不一樣,reset相當於時光倒流到指定的commit id,而revert則是建立合併一個新的提交回退對應的commit提交。現在我們在github上創建一個倉庫,然後在master分支新建test.java文件,分多次順序提交以“第一次提交Test”、“第二次提交 22222”、“第二次提交 33333”。文件內容及提交歷史如下:分別在第二次和第三次追加 System.out.println(22222);System.out.println(33333);
在這裏插入圖片描述
在這裏插入圖片描述

reset

        下面我們手動測試及驗證一下reset的原理,直接在master分支對這幾個提交的commit_id進行reset a0596c92b4be3c99ae16985bf239dd95ac783d0e
git reset --hard a0596c92b4be3c99ae16985bf239dd95ac783d0e,執行一下後,可以看到git log當前本地倉庫master分支的head已經指向了“a0596c92b4be3c99ae16985bf239dd95ac783d0e” commit id,完成了時光倒流,但由於當前遠程倉庫的代碼分支比較靠前,因此如果我們使用git push orign master 會提示錯誤。於是我們只能使用git push -f這樣的危險操作,將本次回退的master內容推向至遠程倉庫,完成本次回退操作的本地與遠程同步。
在這裏插入圖片描述

        通過上述reset的操作與結果,我們可以看到reset的回退更偏向於對於自己本地操作的一個回退,而如果想同步至遠程,則必須使用git push -f這樣危險的強推操作,而在強推的過程中還有可能會覆蓋掉別的夥伴的代碼,因此相對危險。

revert

        接下來對revert進行驗證,我們將基於之前git倉庫的master分支創新的一個分支C_test,即下圖所示,同樣是3次commit。
在這裏插入圖片描述
        接着我們執行revert a0596c92b4be3c99ae16985bf239dd95ac783d0e的操作,git revert -n a0596c92b4be3c99ae16985bf239dd95ac783d0e,然後處理完相應的衝突後可以看到下圖,多出了一次提交,即 f9786a7a7312cfa515。也就是說,我們在revert反做這個commit時,會新建一次新的提交。
在這裏插入圖片描述
        git reset和git revert執行後如下圖所示:
在這裏插入圖片描述

分支上的使用

        上述我們都是在同一個分支進行的git reset和git revert,但是我們在merge 分支時,同樣會產生一個新的commit id,如果我們對這個新的commit id進行回退會怎麼樣?git reset在分支的merge commit上沒有什麼區別,而git
revert則需要更多的注意,下面就操作一下:

初始化分支

        首先我們在master分支創建了Test.java並且提交,接着在這個節點,新建分支A_Test,然後創建A.txt提交到A_Test。如下圖所示:

在這裏插入圖片描述

將A_Test分支合併至master

        接着就進行我們平時操作中的普通操作,將A_Test分支合併至master。如下圖所示,合併後產生一個merge commit id,並且此時master已經比A_Test提前一個節點。
在這裏插入圖片描述

想在master分支回退此次合併

        然後我們發現分支合錯了,不該合併A_Test分支,於是執行了git revert,結構又如下圖所示,master執行回退操作後比A_Test領先了兩步。

在這裏插入圖片描述

將master代碼改動合回A_Test

        master作爲主分支,我們在最後,總要將代碼合回到正在開發的A_Test分支,因此在A_Test分支執行 merge master的操作,我們就會發現,這個時候A_Test做的代碼變動全都被回退了,因爲這個時候分支的情況是下圖,我們的A_Test在合回master代碼的時候,把master在之前做的對於A_Test分支的回退操作也一併合併了回來,因此我們A_Test分支的改動便全都消失了。

在這裏插入圖片描述

        可以看到我們其實在對於分支的合併產生的 commit id進行回退操作時一定要謹慎,reset尚可,一旦執行revert後,再從主分支master向這個A_Tes分支進行合併時,會進行同樣的逆向反做操作,把這個A_Tes分支的所有提交全部回退,因此對於這種情況的revert一定要謹慎,因爲會導致整個分支直接廢掉,所以我們可以使用上面的reset + git push -f這樣的‘危險操作’來回退這次的merge commit。

結語

        本文對於git 回退的reset、revert進行了commit id維度上的操作和原理圖解釋,並且說明了在分支merge情況下如果使用git revert會造成的嚴重後果,即:

  1. 非merge commit id,最好使用Git revert回退,因爲可以產生有效的日誌及操作記錄;
  2. 對於分支間的merge commit id的回退,可以使用git reset + git push -f在本地回退後強推的操作,使對應分支不會作廢。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章