git reset 白話說明:commit 是存檔,reset 是讀檔重來
以「打電動存檔/讀檔」的比喻,用最簡單的方式解釋 git reset 的原理——commit 就是按一次存檔點,reset 就是放棄目前進度、倒回某個存檔點。對應 DHH 談 vibe coding「不會難過地用 git reset 把幾千行沖進馬桶」的情境:因為有存檔點當安全網,丟掉實驗的成本幾乎是零,才敢大膽亂試。含 --hard 與 --soft 差異、常用指令、以及「先 commit 再放心 reset」的關鍵前提。
這頁回答一個常見問題:DHH 在談 vibe-coding-criticality-spectrum 時說,他敢叫 AI 一口氣寫幾千行、
覺得不對就用 git reset 把它們「沖進馬桶」也不心疼——這裡的 git reset 到底在做什麼?
用最白話的方式說明。
全景圖解

整張圖一次看懂:上排是「冒險中 → 存檔(commit) → 讀檔(reset) → 放棄進度丟掉變更」的打電動比喻;
中排對比 reset --soft(回到存檔點但變更保留在暫存區與工作區)與 reset --hard(回到存檔點並清空暫存區與工作區);
下排是常用指令(git log --oneline、reset --soft/--hard <commit>、reset --hard HEAD~1)。
一句話比喻
Git 就像打電動會存檔。每次 git commit 就是按一次存檔點。
git reset= 讀取舊存檔、放棄目前進度,把專案倒回到你選的那個存檔點。
DHH 的情境拆解
- 他叫 AI 一口氣 vibe code 出幾千行——這些還沒存檔(還沒 commit),只是「目前畫面上的改動」。
- 看一看覺得方向不對。
- 一行
git reset --hard,就倒回最後一個存檔點,那幾千行瞬間蒸發,專案乾乾淨淨,像沒發生過。
這就是「不會難過地把幾千行沖進馬桶」的意思:有存檔點當安全網,丟掉實驗的成本幾乎是零,
所以才敢大膽亂試多種可能。這也呼應 dhh-basecamp5-vibe-coding-rails-future 裡 vibe coding 的精神。
心智模型圖
flowchart LR
A[存檔點 A<br/>commit] --> B[存檔點 B<br/>commit]
B --> W[目前畫面上的改動<br/>AI 寫的幾千行<br/>未 commit]
W -. git reset --hard B .-> B
style W stroke-dasharray: 5 5
reset --hard B= 回到存檔點 B,把 B 之後那些「還沒存檔的實驗」全部丟掉。
稍微具體一點:兩種味道
git reset <存檔點> 主要兩種:
git reset --hard <存檔點>— 連同你畫面上的改動一起丟掉,徹底回到那個存檔點的樣子。 (DHH 沖馬桶講的就是這個)git reset --soft <存檔點>— 只把「存檔指標」往回移,但改動還留在畫面上, 給你重新整理、再存一次。
最常用的兩個指令
# 倒回上一個存檔點,丟掉之後所有改動(畫面回到最後一次 commit 的乾淨狀態)
git reset --hard HEAD
# 再往前倒一個 commit
git reset --hard HEAD~1
HEAD= 「目前所在的存檔點」。~1= 「往前一個」,~2就是往前兩個,以此類推。
一個要小心的點(也是 DHH 玩法的前提)
--hard 丟掉的是還沒 commit 的東西,丟了通常救不回來。
所以這套「大膽亂試」成立的關鍵前提是:
真正想留的進度,要先
git commit(先存檔)。
這樣 reset --hard 沖掉的永遠只是「存檔之後的實驗」,不會誤傷你珍惜的成果。
換句話說:勤存檔,才能放心讀檔重來。
總結
commit 是存檔,
reset --hard是讀檔重來。
先養成勤 commit 的習慣,就能像 DHH 一樣,把 AI 寫壞的幾千行一鍵沖掉而不心疼。