iT邦幫忙

2025 iThome 鐵人賽

DAY 5
0
Modern Web

Git 起來!每日一招學起來系列 第 5

Day 5:git reset vs. git restore —— 後悔藥怎麼吃?

  • 分享至 

  • xImage
  •  

在實務專案中,常常會遇到「想把剛剛的動作撤回」的狀況。

Git 在 2.23 版之後,將這類需求拆成兩種命令:

  • git restore:專注於「檔案狀態」的還原
  • git reset:專注於「提交歷史」的回退

兩者功能有部分重疊,但設計理念不同,今天我們就來完整拆解。


三大區域:後悔藥在哪裡發揮?

要搞懂這兩顆藥的差別,先複習 Git 的三大區域:

  1. 工作目錄(Working Directory):實際在電腦上編輯的檔案。
  2. 暫存區(Staging Area / Index):準備被提交的檔案。
  3. 版本庫(Repository):已經正式進歷史的版本。

git resetgit restore 的差異,核心就在於:👉 它們作用的「範圍」不同。


git restore :溫和後悔藥 —— 專治檔案狀態

用於「檔案層級」的操作,處理檔案的修改或暫存。

常見使用場景

  • 還原 工作目錄的修改

    git restore <檔案or目錄>
    
    # 還原檔案
    git restore index.js
    
    # 還原整個目錄
    git restore src/
    

    效果:

    • 情況 1:暫存區沒有修改加入

      工作目錄的修改被還原後,檔案回到 最後一次 commit 的狀態

    • 情況 2:暫存區已有修改加入

      工作目錄的修改被還原後,檔案回到 暫存區的狀態(保留已暫存的修改)

    🔑 記法:restore 還原基準取決於檔案是否暫存

    • 沒暫存 → 回 commit
    • 已暫存 → 回暫存區
  • 退回 暫存區的修改

    git restore --staged index.js
    

    效果:

    • 檔案的修改從暫存區退回工作目錄
    • 修改內容保留,且不會被 commit

👉 可以把 git restore 理解為:只是幫你復原「檔案狀態」,不會亂動 commit 歷史。


git reset :強效後悔藥 —— 回退提交歷史

操作的對象是 HEAD 指標,改變「目前所在的 commit」,並決定是否保留檔案修改。

HEAD 是什麼?

  • HEAD 就是 目前所在的 commit
  • git reset移動 HEAD 到舊的 commit
  • HEAD 移動後,暫存區和工作目錄可能跟著改(取決於模式)

簡單理解:HEAD = Git 裡的「現在位置指標」,操作 reset 就是把指標拉回去。

git reset 的三種模式:退回 commit 內容去哪?

模式 被退回 commit 內容 暫存區 工作目錄
--soft 變成「已暫存的修改」 保留+加入退回 commit 的內容 保留
--mixed(預設) 變成「未暫存的修改」 清空 保留+加入退回 commit 的內容
--hard 直接丟掉 清空 清空

使用方法:

# HEAD退回 上一個 commit,保留修改與暫存
git reset --soft HEAD~

# HEAD退回 上上一個 commit,保留修改,但清除暫存
git reset --mixed HEAD~2

# HEAD退回 上一個 commit,所有修改與暫存都清掉
git reset --hard HEAD~1

這是非常危險的操作,因為一旦刪掉,版本歷史就被改寫了。

💡 小技巧:Git 會把危險操作前的狀態記錄在 .git/ORIG_HEAD

萬一誤刪,可以這樣救回來:

git reset ORIG_HEAD --hard

🔑 記法:

  • --soft → commit 退回到暫存區(等你改訊息、再 commit)
  • --mixed → commit 退回到工作目錄(清空暫存區、等你重新 add)
  • --hard → commit 直接丟掉(暫存區和工作目錄全清空)

⚠️ 特別提醒reset --hard 會清掉所有修改,請務必小心使用!


為什麼 Git 要拆分兩個指令?

在 Git 2.23 之前,很多人習慣用 git reset 來撤銷暫存或丟掉修改
但這樣常常導致誤解甚至誤操作。

所以官方新增了 git restoregit switch,讓指令語意更清晰:

  • reset:操作 commit 歷史
  • restore:管理檔案狀態
  • switch:管理分支 (先知道存在,暫時不展開)

這樣分工之後,使用者能更直覺理解自己在做什麼。


藥如何選擇?

指令 作用範圍 危險程度 適用場景 建議
git restore 檔案層級 🟢 低(安全) 檔案修改錯誤、誤加暫存 小動作用 restore
git reset commit 歷史 🟡🔴 中~高(需謹慎) commit 做錯、想回到舊版本 大動作用 reset

👉 藥這樣選:

  • 如果只是想「退掉檔案變更」或「取消暫存」 → 用 git restore
  • 如果是「回到某個 commit」或「重做提交」 → 用 git reset

git restore = 溫和藥,專治檔案操作,不動歷史,適合日常修正。
git reset = 強效藥,能直接抹掉 commit,危險但強大。


大提醒:reset --hard 真的危險!

很多新手第一次接觸的時候,會覺得它超好用。

但要注意,它會直接把檔案清空回舊狀態,沒有任何回收桶!

👉 如果真的要用,建議先把 commit_id 記下來,避免不小心把重要工作全抹掉。


小挑戰 💪

  1. 在專案中修改一個檔案但不 git add,用 git restore <檔案> 丟掉修改。
  2. 修改一個檔案,先 git add,再用 git restore --staged 把它從暫存區移出。
  3. 建兩個 commit,再用 git reset --soft HEAD~1,觀察修改與暫存的狀態變化。
    ( ⚠️ 請在測試用 Repository 嘗試!)

小結

今天我們學會了兩顆 Git 的「後悔藥」:

  • git restore → 檔案級的後悔藥,還原檔案狀態(取消暫存、丟掉修改)
  • git reset → 歷史級的後悔藥,回退提交歷史(保留或丟棄修改)
  • 千萬小心 git reset --hard,用錯真的會哭

理解它們的差異,就能根據情境選對藥,既能保命,也能避免誤傷。


上一篇
Day 4:git diff —— 看清楚改了什麼
下一篇
Day 6:.gitignore —— 別讓垃圾檔案跟你回家
系列文
Git 起來!每日一招學起來9
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言