『現學現忘』Git後悔藥 — 31、reset版本回退命令總結

繁華似錦Fighting 發表於 2022-07-08
Git

在Git中進行版本回退需要使用git reset命令。

以前面文章中的示例為例,當我準備在V4版本,回退到V3版本的時候,分支中的提交和工作目錄中檔案的狀態,如下圖所示:

image

我們分別執行了三種回退方式:

  • git reset --soft HEAD^:溫柔的回退。
  • git reset --mixed HEAD^:中等回退。
  • git reset --hard HEAD^:強硬的回退。

(我們從英文中就可以看出,一個比一個回退的多。)

下面我們一一進行總結。

1、--soft回退說明

當我在V4版本的時候,執行git reset --soft HEAD^命令回退到V3版本。

Git中發生的變化如下圖所示:

image

依據上圖,理解一下發生的事情:本質上就發生了,把HEAD指標指向了V3版本。而工作區和暫存區中的readme.txt檔案是沒有做任何變動的。

所以你檢視本地版本庫中的readme.txt檔案是V3版本,工作區和暫存區中的readme.txt檔案是V4版本。

就等於回滾到了git commit之前的狀態。

(我前面文章中有詳細的演示)

擴充:

當我繼續修改readme.txt檔案之後,再次提交,會在V3版本之上在建立一個新的commit提交,並移動HEAD指標指向的分支來使其指向該commit提交,這樣依次提交下去,如下圖所示:

image

如果我們使用git log命令檢視本地版本庫的歷史提交資訊的時候,就不會出現V4版本提交的資訊。會是V1V2V3V5。(我們從前面文章中已經演示了)

但是V4版本是不會在Git中刪除的,會永遠的儲存在Git的本地版本庫中。我們可以使用git reflog命令,可以檢視該V4版本的提交資訊。

提示:只要是本地版本庫中HEAD有過的變化,那麼git reflog命令就能夠顯示出來。

(關於這點,下面同理,所以下面就不說了。)

2、--mixed回退說明

當我在V4版本的時候,執行git reset --mixed HEAD^命令回退到V3版本。

Git中發生的變化,如下圖所示:

image

理解一下發生的事情,我們可以看到上圖中,完成了兩步操作:

  1. 把HEAD指標指向了V3版本(也就是版本庫回退了)。
  2. 把暫存區中的readme.txt檔案也回退到了V3版本。

而只有工作區中的readme.txt檔案內容沒有變化。

這說明git reset --mixed命令比git reset --soft命令,多回退了暫存區中的內容。

就等於回滾到了git commitgit add之前的狀態。

(我前面文章中有詳細的演示)

提示:因為--mixed引數是git reset命令的預設選項,也就是不寫任何引數就預設使用--mixed引數。即git reset HEAD^等同於git reset --mixed HEAD^命令

3、--hard回退說明

當我在V4版本的時候,執行git reset --hard HEAD^命令回退到V3版本。

Git中發生的變化,如下圖所示:

image

理解一下發生的事情,我們可以看到上圖中,完成了三步操作:

  1. 把HEAD指標指向了V3版本(也就是版本庫回退了)。
  2. 把暫存區中的readme.txt檔案也回退到了V3版本。
  3. 把工作區中readme.txt檔案的修改也復原了。

所以執行完git reset --hard HEAD^命令,是完全回退一個版本。

此時工作區、暫存區、本地版本庫中的檔案狀態都是一致的,都是V3版本。

就等於回滾了一個“編輯檔案,新增到暫存區,提交版本庫”的整個流程。

(我前面文章中有詳細的演示)

4、總結

必須注意:

--hard引數是git reset命令唯一的危險用法,是能夠使Git會真正地銷燬資料的僅有的幾個操作之一。

其他任何形式的git reset操作都可以輕鬆撤消,但是--hard選項不能,因為它強制覆蓋了工作目錄中的檔案。

在這種特殊情況下,我們的Git資料庫中的一個提交內,還留有該檔案的V4版本,我們可以通過git reflog來找回它。但是若該檔案還未提交,Git仍會覆蓋它從而導致無法恢復。