git stash - 暫存變更

git stash 可以把目前的變更暫時儲存起來,讓工作目錄回到乾淨的狀態。當你需要暫時切換到別的工作時非常有用。

使用情境

  • 開發到一半需要切換分支處理緊急 bug
  • 想要 pull 遠端更新,但有未 commit 的變更
  • 想要暫時保存實驗性的修改

基本用法

暫存變更

git stash

或加上訊息:

git stash push -m "Work in progress on login feature"

這會把所有已追蹤檔案的變更存起來,工作目錄會回到乾淨的狀態。

查看 Stash 列表

git stash list

輸出:

stash@{0}: WIP on main: a1b2c3d Latest commit
stash@{1}: On feature: Work in progress on login feature
stash@{2}: WIP on main: b2c3d4e Previous commit

恢復變更

# 恢復最近的 stash,並從列表中移除
git stash pop

# 恢復最近的 stash,但保留在列表中
git stash apply

恢復特定的 Stash

# 用 stash 的編號
git stash pop stash@{1}
git stash apply stash@{2}

刪除 Stash

# 刪除特定 stash
git stash drop stash@{0}

# 刪除所有 stash
git stash clear

進階用法

包含未追蹤的檔案

預設情況下,git stash 只會暫存已追蹤的檔案。要包含新檔案:

git stash -u
# 或
git stash --include-untracked

包含被忽略的檔案

git stash -a
# 或
git stash --all

只 Stash 部分檔案

# 使用互動模式選擇要 stash 的變更
git stash -p
# 或
git stash --patch

Git 會逐一詢問每個變更是否要 stash。

Stash 特定檔案

git stash push -m "Stash specific files" path/to/file1.js path/to/file2.js

保留暫存區的狀態

預設 stash 會把暫存區和工作目錄一起 stash。如果想保留暫存區:

git stash --keep-index

查看 Stash 內容

查看 Stash 的差異

# 查看最近的 stash
git stash show

# 查看詳細 diff
git stash show -p

# 查看特定 stash
git stash show stash@{1}
git stash show -p stash@{1}

從 Stash 建立分支

如果你 stash 了一些變更,後來想在新分支上繼續開發:

git stash branch new-feature stash@{0}

這會:

  1. 建立新分支 new-feature
  2. 切換到該分支
  3. 套用 stash 並刪除它

實際範例

情境一:緊急切換分支

# 正在 feature 分支開發
# 突然需要去 main 修 bug

# 1. 暫存目前的變更
git stash push -m "Feature work in progress"

# 2. 切換到 main
git checkout main

# 3. 修 bug
git checkout -b hotfix/urgent-bug
# 修改...
git commit -m "Fix urgent bug"

# 4. 合併並回到 feature
git checkout main
git merge hotfix/urgent-bug
git checkout feature

# 5. 恢復之前的工作
git stash pop

情境二:Pull 前清理

# 有未 commit 的變更,但想 pull
git stash
git pull
git stash pop

情境三:測試乾淨狀態

# 想測試沒有目前變更的狀態
git stash
# 測試...
git stash pop

Stash 衝突

恢復 stash 時可能會遇到衝突:

git stash pop
# CONFLICT: 衝突發生

處理方式和 merge 衝突相同:

# 1. 手動解決衝突
code conflicted-file.js

# 2. 標記已解決
git add conflicted-file.js

# 3. stash 不會自動刪除,需要手動刪除
git stash drop

常見問題

Stash 遺失了怎麼辦?

如果不小心 drop 了重要的 stash,可以用 git fsck 找回:

# 找出懸空的 commit
git fsck --no-reflog | grep commit

# 查看內容
git show <commit-hash>

# 套用
git stash apply <commit-hash>

Stash 跨分支使用

Stash 是全域的,不屬於特定分支,所以你可以在一個分支 stash,在另一個分支 pop。

但要注意:如果兩個分支的差異太大,pop 時可能會有衝突。

小技巧

快速暫存並切換

# 一行搞定
git stash && git checkout other-branch

查看 Stash 的建立時間

git stash list --date=relative

輸出:

stash@{0}: WIP on main: 2 hours ago
stash@{1}: On feature: 3 days ago

搭配別名使用

git config --global alias.save 'stash push -m'

# 使用
git save "Work in progress"