Appearance
储藏(Stash)
git stash 是一个临时保存工作区和暂存区状态的工具。当你需要切换分支处理紧急任务,但当前工作还没完成时,stash 可以帮你"搁置"当前进度。
git stash / git stash push
bash
# 储藏当前所有改动(包括已暂存和未暂存的已跟踪文件)
git stash
git stash push # 等价,更明确
# 储藏后工作区恢复干净状态
git status
# nothing to commit, working tree cleangit stash -m 带描述储藏
bash
# 带描述信息储藏(推荐,方便后续识别)
git stash push -m "feat: 用户登录功能进行到一半"
git stash -m "修复中途被打断"
# 带描述的 stash list 显示
git stash list
# stash@{0}: On main: 修复中途被打断
# stash@{1}: On feature/login: feat: 用户登录功能进行到一半git stash list 查看列表
bash
git stash list
# 输出:
# stash@{0}: WIP on main: abc123 feat: 最新提交 ← 最新的 stash
# stash@{1}: On feature/login: 用户登录功能进行到一半
# stash@{2}: WIP on develop: def456 fix: 修复样式
# 显示每个 stash 的改动统计
git stash list --stat
# 显示 stash 的完整差异
git stash show -p stash@{0}
# 查看某个 stash 的内容摘要
git stash show stash@{1}git stash pop vs git stash apply
bash
# pop:恢复并删除最新的 stash(推荐)
git stash pop
# pop 指定的 stash
git stash pop stash@{2}
# apply:恢复但不删除 stash(stash 仍然保留)
git stash apply
git stash apply stash@{1}
# 恢复时同时恢复暂存区状态(默认 apply 不恢复暂存区)
git stash pop --index
git stash apply --indexpop vs apply:
| 命令 | 恢复 stash | 删除 stash |
|---|---|---|
pop | ✅ | ✅ |
apply | ✅ | ❌(stash 仍保留) |
git stash drop / git stash clear
bash
# 删除最新的 stash
git stash drop
# 删除指定 stash
git stash drop stash@{2}
# 删除所有 stash
git stash cleargit stash branch 从储藏创建分支
当 stash 的内容与当前代码冲突时,可以将 stash 创建为新分支:
bash
# 从 stash 创建新分支(恢复 stash 时基于 stash 创建时的提交)
git stash branch feature/stashed-work
# 指定 stash
git stash branch fix/saved-work stash@{2}这相当于:
- 创建新分支(基于 stash 储藏时的提交)
- 在新分支上应用 stash
- 删除 stash
git stash -p 交互式储藏
选择性地储藏部分改动(类似 git add -p):
bash
git stash -p
git stash push -p # 等价
# 会显示每个 hunk,提示操作:
# Stash this hunk [y,n,q,a,d,/,e,?]?
# y - 储藏此块
# n - 不储藏此块(保留在工作区)
# q - 退出
# a - 储藏此文件的所有块
# ...git stash --include-untracked 包含未跟踪文件
默认情况下,git stash 不储藏未跟踪的文件(新建但未 git add 的文件):
bash
# 包含未跟踪文件
git stash --include-untracked
git stash -u # 简写
# 包含未跟踪文件和被 .gitignore 忽略的文件
git stash --all
git stash -a # 简写(谨慎使用,会储藏 .gitignore 的文件)实际使用场景
场景1:紧急切换分支
bash
# 正在 feature 分支上开发,突然需要修复线上 bug
git stash push -m "feat: 用户登录功能-进行到认证逻辑部分"
# 切换到 main 修复 bug
git switch main
git switch -c hotfix/urgent-bug
# 修复 bug...
git commit -m "fix: 修复用户无法登录的问题"
git switch main
git merge hotfix/urgent-bug
git push
# 回到功能开发
git switch feature/user-login
git stash pop场景2:提交前临时保存测试代码
bash
# 添加了一些临时调试代码
git stash push -m "临时调试代码(不提交)"
# 提交正式的改动
git add .
git commit -m "feat: 添加用户头像功能"
# 恢复调试代码继续调试
git stash pop场景3:在错误分支上开发了代码
bash
# 发现在 main 分支上开发了功能(应该在 feature 分支)
git stash
# 创建并切换到正确的分支
git switch -c feature/new-feature
# 恢复代码到新分支
git stash pop场景4:测试 stash 内容是否适用于当前分支
bash
# 先预览 stash 的内容
git stash show -p stash@{0}
# 在新分支上试验
git stash branch trial-branch stash@{0}
# 如果不合适,直接删除这个分支stash 的存储结构
每个 stash 实际上是一个特殊的 commit 对象:
bash
# 查看 stash 的详细信息
git cat-file -p stash@{0}
# 包含三个父提交:
# 1. 储藏时的 HEAD(当前提交)
# 2. 暂存区内容(作为 commit)
# 3. 未跟踪文件(如果有 -u)总结
| 操作 | 命令 |
|---|---|
| 储藏当前改动 | git stash push -m "描述" |
| 查看 stash 列表 | git stash list |
| 恢复并删除 | git stash pop |
| 只恢复不删除 | git stash apply |
| 删除 stash | git stash drop stash@{n} |
| 清空所有 stash | git stash clear |
| 从 stash 创建分支 | git stash branch <name> |
| 包含未跟踪文件 | git stash -u |
| 交互式储藏 | git stash -p |
Stash 是处理工作中断的利器,但不要把它当作长期存储的工具。对于需要长期保存的工作进度,应该创建一个 WIP(Work In Progress)提交或分支。