Git: 讓你的代碼回到過去,git reset 與 git revert 的用處

Roy Kwok
8 min readMar 6, 2018

先簡單瞭解檔案存入 repository(倉庫)的流程

Git 簡單來説分為三個區域:

1、工作區(working directory): 我們實際操作的資料夾(檔案)

2、暫緩區(stage snapshot): 將工作區檔案的快照新增到暫存區域

3、git 目錄(.git directory): 提交暫存區域的檔案快照永久地儲存在 Git 目錄

git reset — hard and — soft 穿梭你提交的版本之間

  • hard git reset --hard HEAD :此種模式完全不保留原始 commit 結點的任何資訊,會連同資料夾中實體檔案內容都進行重置,也就是直接將工作區、暫緩區及 git 目錄都重置成目標Reset結點的資料內容。

具體操作

回復到上一個(或更前的)版本。
git reset --hard HEAD 回復到最新提交版本
git reset --hard HEAD~ // 等於 ~1 回復到上一個提交版本
git reset --hard HEAD~n // n 等於往上第幾個提交版本 回復之前指定的提交版本

例子一:

假設我發現最新的代碼版本有bugs,想回復更前的版本,你可以輸入: git log --oneline -n // (n 是最近幾多次的提交記錄)

如下所示,便會顯示最近5次的提交記錄。

Kwokde-MacBook-Pro:test stevechung$ git log --oneline -5 // 最近5次提交記錄
ba2f0a4 (HEAD -> master, origin/master) test4 //最新提交的記錄
f3a6683 test1 // 上一個提交的記錄
4f0f054 test2
6fefa2d test1
77f9ec8 reset

如果你想回復到 f3a6683 test1 ,
輸入 git reset --hard HEAD~ 如果你想回復到 4f0f054 test2 ,
輸入 git reset --hard HEAD~2 如果你想回復到 6fefa2d test1 ,
輸入 git reset --hard HEAD~3 如此類推。

假設我回復到 4f0f054 test2 這個版本,輸入後便會顯示:

Kwokde-MacBook-Pro:test stevechung$ git reset --hard HEAD~2 // 回覆到 4f0f054 test2
HEAD is now at 4f0f054 test2 // 這代表成功回至你指定的版本

— hard 使用注意⚠️:如果修改了內容,執行了git add,但沒有執行git commit 執行 git reset — hard 會刪除了已git add 但未git commit 的修改內容。

小知識:
HEAD 是什麼 ? HEAD 是一個指標,指向某一個分支,通常你可以把 HEAD 當做「目前所在分支」看待。

假設你回覆之前的版本後,又想回復到最新提交的版本,就可以用:

  • git reflog :查看所有訊息版本
  • git reset --hard commit_id : 根據 commit id 回覆到指定版本

例子二:

你可以輸入 git reflog 查看所有訊息版本,如下所示:

Kwokde-MacBook-Pro:test stevechung$ git reflog // 查看所有訊息版本
4f0f054 (HEAD -> master) HEAD@{0}: reset: moving to HEAD~2 // 這是例子一、回的當前提交記錄
ba2f0a4 (origin/master) HEAD@{1}: commit: test4 // 假設你要回復到例子一、開頭使用的這個版本
f3a6683 HEAD@{2}: commit: test1
4f0f054 (HEAD -> master) HEAD@{3}: commit: test2
6fefa2d HEAD@{4}: commit: test1
77f9ec8 HEAD@{5}: commit: reset
58f0631 HEAD@{6}: reset: moving to HEAD
58f0631 HEAD@{7}: commit (initial): gitreset

ba2f0a4 就是 commit id,每個經 git commit -m "" 提交到歷史記錄區(倉庫)都會生成一組 commit id,可以按以下輸入:

Kwokde-MacBook-Pro:test stevechung$ git reset --hard ba2f0a4 //回到的指定commit id 的提交記錄版本
HEAD is now at ba2f0a4 test4 // 這代表成功回至你指定的版本
  • soft git reset --soft HEAD / commit id :此模式下會保留工作區資料內容,不會異動到目前所有的實體檔案內容;也會保留暫緩區資料內容,讓暫緩區與 git 目錄資料內容是一致的。

具體操作:

Kwokde-MacBook-Pro:test raykwok$ git reflog // 查看所有訊息版本
ba2f0a4 (HEAD -> master, origin/master) HEAD@{0}: reset: moving to ba2f0a4
4f0f054 HEAD@{1}: reset: moving to HEAD~2
ba2f0a4 (HEAD -> master, origin/master) HEAD@{2}: commit: test4
f3a6683 HEAD@{3}: commit: test1
4f0f054 HEAD@{4}: commit: test2
6fefa2d HEAD@{5}: commit: test1 // 計劃回到前 3 個版本 - 6fefa2d
77f9ec8 HEAD@{6}: commit: reset
58f0631 HEAD@{7}: reset: moving to HEAD
58f0631 HEAD@{8}: commit (initial): gitreset
Kwokde-MacBook-Pro:test raykwok$ git reset --soft HEAD~3 // 回到 6fefa2d 版本
Kwokde-MacBook-Pro:test raykwok$ git reflog
6fefa2d (HEAD -> master) HEAD@{0}: reset: moving to HEAD~3 // 回成功
ba2f0a4 (origin/master) HEAD@{1}: reset: moving to ba2f0a4
4f0f054 HEAD@{2}: reset: moving to HEAD~2
ba2f0a4 (origin/master) HEAD@{3}: commit: test4
f3a6683 HEAD@{4}: commit: test1
4f0f054 HEAD@{5}: commit: test2
6fefa2d (HEAD -> master) HEAD@{6}: commit: test1
77f9ec8 HEAD@{7}: commit: reset
58f0631 HEAD@{8}: reset: moving to HEAD
58f0631 HEAD@{9}: commit (initial): gitreset

git revert 撤銷一個提交的同時會創建一個新的提交。

  • revert git revert HEAD 新增一個 Commit 來反轉(或説取消)另一個 Commit 的內容,原本的 Commit 依舊還是會保留在歷史紀錄中。雖然會因此而增加 Commit 數,但通常比較適用於已經推出去的 Commit,或是不允許使用 Reset 或 Rebase 之修改歷史紀錄的指令的場合。

具體操作:

Kwokde-MacBook-Pro:test raykwok$ git revert HEAD~2 // 提交revert 取消上一次提交
[master 1b6942a] Revert "gitreset" // 增加了一個 Commit 1b6942a 用以代替上次提交的版本
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 README.md
Kwokde-MacBook-Pro:test raykwok$ git reflog
1b6942a (HEAD -> master) HEAD@{0}: revert: Revert "gitreset" // 增加一個 Commit 來取消 6fefa2d
6fefa2d HEAD@{1}: reset: moving to HEAD
6fefa2d HEAD@{2}: reset: moving to HEAD~3

關於git的基本使用,可參考:圖文代碼並茂簡潔教學 Git 的基本使用

--

--