跳轉到

Reverting versions

前情提要

首先,工作目錄暫存區提交紀錄 的檔案內容是一致的。

當實體檔案被異動後,工作目錄 的檔案內容會與 暫存區提交紀錄 的不一致: * 若檔案不曾被提交過,此時的檔案狀態為 Untracked files * 若檔案曾被提交過,此時的檔案狀態為 Changes not staged for commit

接著,當我們執行 git add <file>... 後,會將這些異動的檔案內容加入 暫存區 中 (Changes to be committed)。此時,工作目錄暫存區 的檔案內容是一致的,但卻與 提交紀錄 (HEAD) 的檔案內容不一致。

最後,執行 git commit 並將所有異動的檔案內容提交 (push) 至 Repository 中。待建立出新的 Commit 結點後,工作目錄暫存區提交紀錄 中的檔案內容便會保持一致。

情境 1:單一檔案退版

  1. 退回 "檔案狀態"
    # Unstage file
    git reset HEAD <file>
  1. 退回 "檔案內容"
    # Discard changes in working directory
    git checkout <file>

補充:git checkout -- <file>... 是一個危險的命令, 對指定檔案所做的任何修改都會消失 —— Git 只是複製了另一個檔案來覆蓋它。除非你很肯定地知道你不想要那個檔案了,否則千萬不要使用這個命令

情境 2:本地檔案退版

假設以下情境:

~ 工作目錄
(Working Tree)
暫存區
(Staging Area)
提交紀錄 異動內容
HEAD~3 - - commit1 change1.txt
HEAD^^
(HEAD~2)
- - commit2 change2.txt
HEAD^
(HEAD~1)
- - commit3 (HEAD) change3.txt
本地端 change4.txt - - -

使用 Reset 的三種模式

  1. --soft:這個模式下會保留工作目錄和暫存區的檔案 (本次異動),提交紀錄的異動內容會直接放在暫存區,所以看起來就只有 HEAD 的移動而已
    git reset --soft HEAD
~ 工作目錄
(Working Tree)
暫存區
(Staging Area)
提交紀錄 異動內容
本地端 change4.txt change3.txt commit2 (HEAD) -
  1. --mixed (預設):這個模式會把暫存區的檔案移動到工作目錄 (本次異動),提交紀錄內異動的內容會直接放在工作目錄,不會留在暫存區
    git reset HEAD
~ 工作目錄
(Working Tree)
暫存區
(Staging Area)
提交紀錄 異動內容
本地端 change3.txt
change4.txt
- commit2 (HEAD) -
  1. --hard:這個模式下,不論是本次異動或提交紀錄內異動的內容都會移除
    git reset --hard HEAD
~ 工作目錄
(Working Tree)
暫存區
(Staging Area)
提交紀錄 異動內容
本地端 - - commit2 (HEAD) -

以記錄退版

  • git reflog:每當 HEAD 有移動的時候,Git 就會在 Reflog 裡記上一筆
  • git log:加入 -g 參數,同樣可以看到 Reflog
    git reset --hard <log>

以標籤退版

    git reset --hard <tag>