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}
這會:
- 建立新分支
new-feature - 切換到該分支
- 套用 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"