Git Reset:退回版本與分支拆分指南
更新日期: 2024 年 12 月 9 日
本文為 Git 指令基本介紹教學,第 4 篇:
- Git 新手入門指南
- Git 分支與版本控制入門指南
- Git merge 與 rebase 初學者指南
- Git Reset:退回版本與分支拆分指南 👈 所在位置
- 解決 Git 衝突 (Conflict) 的完整指南
Git 是一個功能強大的版本控制工具,其中 git reset
是一個用來修改版本歷史與狀態的指令。
它可以幫助我們將分支、HEAD
或檔案狀態退回到特定的節點,並根據需求調整檔案的狀態。
本篇文章將以簡單明瞭的方式說明 git reset
的運作原理與使用方法。
什麼是 Git Reset?
在了解 git reset
的功能之前,先來認識 Git 的三個核心工作區域:
- 工作目錄 (Working Directory)
- 這是您直接編輯和操作檔案的地方。
- 當您新增、修改或刪除檔案時,這些變更會首先反映在工作目錄中。
- 例如,當您在編輯器中撰寫程式碼並儲存後,這些變更僅存在於工作目錄中,尚未被 Git 追蹤。
- 暫存區 (Staging Area)
- 暫存區是 Git 用來準備提交變更的區域。
- 當您使用
git add
指令時,檔案的變更會從工作目錄移動到暫存區。 - 暫存區的作用類似於「草稿」,讓開發者可以選擇哪些檔案或變更要提交到儲存庫中。
- 儲存庫 (Repository)
- 儲存庫是 Git 用來永久儲存檔案歷史的地方。
- 當您使用
git commit
時,暫存區的內容會被提交到儲存庫,成為一個可以追蹤的版本 (commit)。 - 儲存庫中的內容不會受到後續檔案修改的影響,直到再次執行新的提交。
+-------------------------+
| Working Directory |
| 本地檔案的編輯與修改 |
+-------------------------+
|
| git add
v
+-------------------------+
| Staging Area (Index) |
| 暫存的更改,用於準備提交 |
+-------------------------+
|
| git commit
v
+-------------------------+
| Repository |
| 已提交的版本庫記錄 |
+-------------------------+
git reset
的三種模式
git reset
是一個靈活且功能強大的指令,它提供三種模式來控制檔案在 Git 的三個工作區域(工作目錄、暫存區、儲存庫)之間的狀態轉移。
不同模式適用於不同的回退需求,以下將逐一說明。
--hard
模式
- 功能:
將HEAD
指標移動到指定的提交點,並清除工作目錄和暫存區的所有變更。
無論是未提交的修改,還是已加入暫存區的內容,皆會恢復到指定版本的狀態。 - 適用情境:
適合捨棄所有變更並徹底恢復到特定版本的情境。例如,發現近期的修改不符合需求且不需保留時,可使用--hard
模式進行回退。 - 指令範例:
git reset --hard <commit-id>
- 注意事項:
使用--hard
時需謹慎,因為所有未提交的內容將無法恢復。
--soft
模式
- 功能:
將HEAD
指標移動到指定的提交點,保留工作目錄的變更,並將所有變更內容保存在暫存區中。
這讓您可以立即進行新的提交,而不需要重新執行git add
。 - 適用情境:
適合在回退版本後重新整理提交歷史的情況。例如,將多次提交合併為一次更精簡的提交,或者修正先前提交的描述內容。 - 指令範例:
git reset --soft <commit-id>
- 操作結果:
- 工作目錄保持不變,所有檔案內容仍可見。
- 暫存區的內容自動更新為指定版本的狀態。
--mixed
模式(預設值)
- 功能:
將HEAD
指標移動到指定的提交點,保留工作目錄的變更,但清空暫存區的內容。
這意味著工作目錄中的變更,需要重新選擇哪些檔案要提交到暫存區。 - 適用情境:
適合退回版本後,對檔案進行進一步整理的情況。
例如,當您需要分批提交內容或重新選擇哪些檔案需要包含在下一次提交中時,可以使用此模式。 - 指令範例:
git reset --mixed <commit-id>
- 操作結果:
- 工作目錄保留所有變更內容。
- 暫存區被清空,變更未被追蹤,需重新執行
git add
。
Reset 的視覺化說明
以下示意圖展示了 git reset
的操作流程,幫助理解三種模式的效果。
基本分支狀態
A -- B -- C [HEAD, master]
--hard
模式
指令:
git reset HEAD~1 --hard
結果:
A -- B [HEAD, master]
- C 被捨棄:工作目錄與暫存區清空,狀態恢復到提交
B
。
--soft
模式
指令:
git reset HEAD~1 --soft
結果:
A -- B [HEAD, master]
(暫存區保留 C 的變更)
- C 的內容保留在暫存區:工作目錄保持不變,可直接重新提交。
--mixed
模式(預設)
指令:
git reset HEAD~1 --mixed
結果:
A -- B [HEAD, master]
(C 的內容回到工作目錄)
- C 的內容回到工作目錄:暫存區清空,需要重新選擇提交的檔案。
三種模式的比較
模式 | 工作目錄 | 暫存區 | 適用情境 |
---|---|---|---|
--hard | 恢復到指定版本 | 清空 | 捨棄所有變更並完全恢復到指定版本 |
--soft | 保留 | 保留 | 保留變更並準備立即重新提交 |
--mixed | 保留 | 清空 | 保留變更內容,重新選擇提交的檔案 |
以 HEAD
為基準進行 Reset
Git 使用 HEAD
來指向當前分支的最新提交。
我們可以通過 HEAD
快速執行版本退回。
常用指令
- 退回到上一個提交
HEAD^
表示上一個提交。--hard
表示清空工作目錄和暫存區的變更。
git reset HEAD^^ --hard
- 退回到前兩個提交
~2
表示向上退回兩個提交。
git reset HEAD^^ --hard
或
git reset HEAD~2 --hard
- 結合分支名稱 使用分支名稱代替
HEAD
,如:- 將
master
分支退回到前兩個提交,並將變更保留在暫存區。
- 將
git reset master~2 --soft
使用 Reset 重新拆分合併的分支
在進行分支合併後,如果需要將分支拆開,可以使用 git reset
退回到合併前的狀態。
操作步驟
- 假設分支
feature
已與master
合併:
git merge feature
- 使用
git reset
退回到合併前的狀態:- 合併狀態將被撤銷,分支將重新拆分。
git reset HEAD~1 --hard
- 若需要重新進行合併,只需再次執行合併指令:
git merge feature
查詢歷史版本:git reflog
如果無法記住版本的提交 ID,可以使用 git reflog
查詢歷史操作紀錄。
指令範例
git reflog
輸出範例:
c60fbcd HEAD@{0}: merge feature: Fast-forward
1908ada HEAD@{1}: commit: Added new feature
1234abcd HEAD@{2}: reset: moving to HEAD~1
HEAD@{n}
表示操作的順序。- 可用於快速定位並回到特定節點:
git reset HEAD@{2} --hard
結語
git reset
是一個靈活且強大的工具,可以用來撤銷提交、退回版本,甚至重新拆分合併分支。