git stash 是什么
git stash 把当前已跟踪文件的改动与暂存状态打包保存起来,让工作区回到干净状态,之后再取回来继续。它适合「手上改到一半、突然要切分支处理别的事」这类被打断的场景。默认不包含未跟踪的新文件,也不包含被忽略的文件。
它到底是什么
stash 本质上是保存在 refs/stash 下的一个特殊提交对象,整个 stash 是一条栈,stash@{0} 是最新一条。理解这一点就能解释不少行为:它可以在任意分支上取出,与当前分支无关;遇到冲突时按当前分支的内容解决;它也不会自动清理,需要 pop 或 drop 才会消失。
基本信息
| 适用平台 | Linux / macOS / Windows(Git 2.x) |
|---|---|
| 默认范围 | 已跟踪文件的改动与暂存状态 |
| 扩展范围 | -u 含未跟踪文件;-a 含被忽略文件 |
| 栈引用 | stash@{0} 为栈顶,编号越小越新 |
| 查看 | git stash list 列表;git stash show -p 看具体内容 |
| 清理 | git stash drop 删单条;git stash clear 清空全部 |
典型使用场景
- 紧急打断:改到一半要去处理线上问题,先存现场再切分支
- 同步代码:本地改动挡住 pull 或变基时先 stash 再同步
- 对比验证:暂时存下改动,看干净代码是否也有同样问题
- 跨分支搬运:让现场在另一条分支上取出来继续做
- 方案比较:同一问题试两种实现,用 stash 在两者之间切换
- 带消息管理:用 -m 给记录加说明,避免久了认不出是哪件事
常用示例
常用示例
git stash push -m 'wip: api 重构' # 保存现场并加上说明
git stash push -u # 连未跟踪的新文件一起保存
git stash list # 查看栈里有哪些记录
git stash show -p stash@{0} # 查看某条记录的具体改动
git stash apply stash@{1} # 取回来但保留栈记录
git stash pop # 取回最新一条并出栈
git stash drop stash@{0} # 删除某条记录
git stash clear # 清空整个栈常用子命令
| 子命令 | 作用 | 注意 |
|---|---|---|
| push -m | 保存现场并写说明 | 默认不含未跟踪文件 |
| push -u | 把未跟踪文件一起保存 | 被忽略文件仍需 -a |
| list | 列出栈内全部记录 | 编号越小越新 |
| show -p | 查看某条记录的补丁 | 不加编号则看栈顶 |
| apply | 取回但保留记录 | 重复使用容易混淆 |
| pop | 取回并删除记录 | 冲突时不会删除,避免丢现场 |
stash 是 refs/stash 上的提交对象,所以它与分支无关,可以在任意分支上 pop;冲突时按当前分支的内容解决即可。
栈里的记录不会自动过期,长期不清理会混进后来完全无关的现场。用完及时 pop 或 drop,不要把它当成长期暂存区使用。
丢弃现场前先用 git stash list 与 git stash show -p 确认内容。git stash clear 会一次清空全部记录,而且没有二次确认。
未跟踪的新文件默认不入栈,需要加 -u。漏加时工作区看起来「干净」,可切分支时新文件会跟着跑到目标分支,容易让人困惑。
取回现场时的冲突
apply 或 pop 时,如果栈里的改动与当前分支的文件内容冲突,Git 会报错并列出冲突文件。此时那条 stash 记录不会被删除,pop 也一样保留,这是刻意的保护设计,避免现场丢掉。按普通冲突流程解决并 git add 之后,再手动 git stash drop 清理掉这条已经用过的记录。
只想查看某条记录而不改动工作区,用 git stash show -p stash@{n} 看补丁;想把记录直接变成一条新分支继续开发,用 git stash branch。
stash 记录同样是提交对象,误 drop 之后短期内还有机会通过 git fsck --unreachable 找到悬空提交并恢复,但不要把它当成可靠的兜底手段。真正重要的进度应该落到提交上,而不是留在栈里。