『現學現忘』Git後悔藥 — 32、revert復原(一)

2022-10-13 15:03:13

1、Git的三種後悔藥

在Git中後悔藥有三種:amendrevertreset

  • git commit --amend:新的提交覆蓋上一次提交的內容。
  • git revert:提交一個新的commit,來複原之前的commit
  • git reset:直接回滾到指定的commit
    --soft:只回退版本庫,工作區和暫存區的內容不回退。
    --mixed(預設):回退版本庫和暫存區,工作區中的內容不回退。
    --hard:工作區,暫存區,版本庫中的內容都回退到指定的提交。(危險的)

提示:之前我們把git reset命令說完了,git commit --amend命令我們下一篇文章說。這篇文章來說git revert命令。

2、revert命令原理

在我們使用Git的操作中,遇到需要回滾程式碼的情況幾乎是難以避免的,而 git revert 命令是一個非常實用的功能,掌握好 git revert 命令的使用是很有必要的。

git revert命令:是用於「反做」某一個版本,以達到復原該版本的修改的目的。

比如,我們提交了三個版本,突然發現版本二不行(如:有bug),想要復原版本二,但不想或不需要復原版本三提交,就可以用 git revert 命令來反做版本二,同時生成新的版本四,這個版本四里會保留版本三的東西,但復原了版本二的東西。

但注意:版本二的歷史提交記錄是不會刪除的。

如下圖所示:

提示:注意是revert命令撤回某個改動,不是reset命令撤回到某個改動。另外,這條命令不會刪除任何commit記錄,而是會新增一條revert操作的commit記錄(會彈出commit message的編輯視窗)。

3、revert命令的使用

現有一個版本庫,其中有4次提交,版本庫的歷史提交記錄如下:

L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/revert_test (master)
$ git log --oneline
c04b29c (HEAD -> master) 第4次提交,新增內容:revert test v4
fd819dc 第3次提交,新增內容:revert test v3
c71ae3c 第2次提交,新增內容:revert test v2
557f7c3 第1次提交,新增readme.txt檔案

我們發現第三次提交和第四次提交有錯誤,需要復原。

如下圖:

(1)移除某次提交的修改

commit-1commit-2 是正常提交,而 commit-3commit-4 是錯誤提交。現在,我們想把 commit-3commit-4 復原掉。而此時,HEAD 指標指向 commit-4 提交(c04b29c)。我們只需將 HEAD 指標移動到commit-2 提交(c71ae3c),就可以達到目的。

我們一定會想到之前學過的 git reset 命令。執行命令git reset --hard c71ae3c,就可以退回到 commit-2 提交。

採用這種方式回退程式碼的弊端顯而易見,那就是會使 HEAD 指標往回移動,從而會失去之後的提交資訊。將來如果突然發現, commit-3commit-4 是多麼絕妙的想法,可它們已經早就消失在歷史的長河裡了(但是通過reflog也能找回來)。

而且,有些公司明令禁止使用 git reset 命令去回退程式碼,原因與上述一樣。所以,我們需要找到一個命令,既可以回退程式碼,又可以儲存錯誤的提交。這時 git revert 命令就派上用場了。

命令:git revert <commit>

演示:

# 1.復原第四次提交
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/revert_test (master)
$ git revert c04b29c
[master d0c8e48] Revert "第5次提交,revert 復原第4次提交"
 1 file changed, 1 deletion(-)

# 之後會彈出一個編輯文字方塊,來讓你寫新生成提交的註釋,如下圖。

# 2.檢視版本庫歷史提交記錄
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/revert_test (master)
$ git log --oneline
d0c8e48 (HEAD -> master) Revert "第5次提交,revert 復原第4次提交"
c04b29c 第4次提交,新增內容:revert test v4
fd819dc 第3次提交,新增內容:revert test v3
c71ae3c 第2次提交,新增內容:revert test v2
557f7c3 第1次提交,新增readme.txt檔案
# 可以看到第4次提交的commit依然存在。

# 3.檢視readme.txt檔案內容
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/revert_test (master)
$ cat readme.txt
revert test v1
revert test v2
revert test v3
# 可以看到V4 版本內容已經沒有了。

如下圖所示:

這裡需要說明一下:

git revert命令的作用通過反做建立一個新的版本,這個版本的內容與我們要回退到的目標版本一樣,但是HEAD指標,是指向這個新生成的版本,而不是目標版本。

使用 git revert 命令來實現上述例子的話,我們可以這樣做:先 revert commit-4,再 revert commit-3有多個提交需要回退的話需要由新提交到舊提及哦啊進行 revert)。

我們繼續同樣的操作步驟,把第三次提交也復原掉。

# 1.復原第3次提交
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/revert_test (master)
$ git revert fd819dc
[master 30f7626] Revert "第6次提交,revert 復原第3次提交"
 1 file changed, 1 deletion(-)

# 2.檢視版本庫歷史提交記錄
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/revert_test (master)
$ git log --oneline
30f7626 (HEAD -> master) Revert "第6次提交,revert 復原第3次提交"
d0c8e48 Revert "第5次提交,revert 復原第4次提交"
c04b29c 第4次提交,新增內容:revert test v4
fd819dc 第3次提交,新增內容:revert test v3
c71ae3c 第2次提交,新增內容:revert test v2
557f7c3 第1次提交,新增readme.txt檔案

# 3.檢視readme.txt檔案內容
L@DESKTOP-T2AI2SU MINGW64 /j/git-repository/revert_test (master)
$ cat readme.txt
revert test v1
revert test v2

通過上面練習,我們可以得出,git reset復原和git revert復原的區別,如下圖所示:

(2)revert命令說明

git revert <commit>命令:

  1. 這個命令會生成一個新的提交記錄,新的提交記錄就是把需要移除的提交復原掉,所生成的新提交。
  2. 如果工作區或暫存區還有修改未提交,那麼會提示需要先提交或儲存起來這些檔案。
  3. 如果在移除的過程中發生了衝突,可以在解決了衝突後,使用 git add 命令新增修改的衝突檔案到暫存區中,在使用 git revert --continue 來繼續操作。
    如果不想繼續操作,當然也可以使用 git revert --abort 命令來停止移除操作,恢復到執行git revert <commit>命令之前的狀態。
  4. 如果revert移除的過程中出現衝突,需要把這些衝突解決才可以繼續操作。我們可以使用 git revert --skip 命令來跳過一個commit的衝突解決。如果後續還有衝突,也同樣如此進行跳過,直到全部衝突解決完成。
    但是使用git revert --skip 命令跳過的commit,將會在歷史提交記錄中被刪除(reflog命令還是可以看到的),所以git rebase --skip 這個命令慎用。

拓展思路:

  • git revert HEAD:復原前一次commit
  • git revert HEAD^:復原前前一次commit