Git Stash不只是临时存代码
你是不是也这样用过 Git stash?
git stash # 紧急切分支,先藏起来
git stash pop # 回来再恢复
停。这就太浪费 stash 的能力了。
stash 是 Git 里被严重低估的功能。用好它,你能解决很多"尴尬切换"的场景,甚至用它来做跨分支的代码流转。
下面我把 stash 从基础到进阶全部捋一遍。全是实战,不整虚的。
一、stash 的基本操作:save vs pop vs apply
先搞清楚三个核心命令的区别。
git stash save(已废弃,了解即可)
老版本用 git stash save "描述" 来命名存储。现在官方已经不推荐了,替代方案在后面。
git stash push(现代写法)
git stash push -m "feature: 临时保存登录页修改"
push 是 save 的现代替代品,支持 -m 加描述,也支持 -u 把 untracked 文件一起存。
git stash apply vs git stash pop
这是很多人搞混的地方。
| 命令 | 从栈中移除? | 适用场景 |
|---|---|---|
git stash apply | 否 | 想恢复但不想丢原始记录 |
git stash pop | 是 | 恢复完就删掉,干净利落 |
简单记:需要保留记录用 apply,不需要用 pop。
git stash list — 查看存储列表
$ git stash list
stash@{0}: On main: 临时保存登录页修改
stash@{1}: On feature/ui: 表单验证改动
stash@{2}: WIP on main: a3f2b1c 修复bug
编号从 0 开始,0 是最新的。
二、5个高频实战场景
场景1:正在修bug,突然要切分支处理紧急需求
# 当前在 main 分支,改了3个文件还没 commit
git status
# modified: src/login.tsx
# modified: src/api/user.ts
# modified: tests/test_login.py
# 不用 commit,直接 stash
git stash push -m "login页未完成修改"
# 切分支处理紧急需求
git checkout hotfix/payment
# ... 处理紧急需求,commit,push
# 回到 main 继续
git checkout main
git stash pop
# 你的修改回来了,继续推进
场景2:多个 stash 之间切换
# 列出所有 stash
git stash list
# 恢复指定 stash(不按顺序)
git stash apply stash@{2}
# 恢复后再删除
git stash pop stash@{1}
场景3:只 stash 部分文件(而不是全部)
# 查看当前修改的文件
git status
# 交互式选择要 stash 的文件
git stash push -p
# 终端会一个个文件问你:"Stash this hunk? (y/n/a/d/s/?) "
# y = 存这个块, n = 跳过, a = 存全部, d = 删全部, s = 拆分
-p(patch)模式非常实用。比如你改了 A 文件和 B 文件,只想暂存 A 文件的部分改动,B 文件留着继续开发。
场景4:把 stash 转移到另一个分支
这是很多人不知道的技巧。stash 默认存在当前分支上,你想在其他分支用怎么办?
# 假设你在 feature 分支创建了 stash
git stash push -m "测试代码"
# 切到 main 分支
git checkout main
# 无法直接用 stash,因为 stash 关联的是 feature 分支的提交
# 解决方法:先 apply 再切分支
git checkout feature
git stash apply
# 现在有代码了,切到 main
git checkout main
# 合并或 cherry-pick 你想要的提交
git merge feature --no-ff
或者更优雅的方式——用 git stash branch 一步到位:
git stash branch temp-fix stash@{0}
# 这条命令会:
# 1. 基于 stash 创建时的分支创建新分支
# 2. 自动 apply stash 的内容
# 3. 把你切换到新分支
场景5:清理无用的 stash
# 清理所有已应用的 stash
git stash drop stash@{2}
# 清理超过1天的 stash
git stash clear
# 只保留最近的3个,其余全部删除
git stash list | tail -n +4 | cut -d: -f1 | xargs -I {} git stash drop {}
三、stash 的隐藏参数
-u:包含 untracked 文件
默认情况下,stash 不会存新建但未跟踪的文件。加上 -u:
git stash push -u -m "连新建文件一起存"
相当于 git add . 然后再 stash。
-k:stash 和 working tree 都保留
git stash push -k -m "双份备份"
stash 之后,你的工作区改动不会被清空。适合你需要同时访问两份代码的场景。
–include-untracked:别名写法
和 -u 效果一样,看个人习惯。
四、常见坑和避坑指南
坑1:stash 后恢复出现冲突
git stash pop
# CONFLICT (content): Merge conflict in src/login.tsx
如果 stash 后主分支有其他提交,pop 时可能冲突。解决方法:
# 查看冲突详情
git diff
# 手动解决冲突
# 编辑文件,去掉 <<<< ==== >>>> 标记
# 解决后继续
git add src/login.tsx
git stash pop --continue
坑2:stash 太多忘了清理
$ git stash list
stash@{0}: ...
stash@{1}: ...
stash@{2}: ...
stash@{3}: ...
stash@{4}: ...
stash@{5}: ...
五个以上的 stash 就是负担。定期清理:
# 查看 stash 占用空间
git fsck --no-reflog | grep dangling | wc -l
# 清理所有已应用的 stash
git stash clear
坑3:在 detached HEAD 状态下 stash
git checkout v1.2.0
git stash push -m "在tag上修改"
# 警告:stash 在 detached HEAD 状态下行为可能不稳定
不建议在 detached HEAD 上做 stash。先创建一个临时分支:
git checkout -b temp-v1.2.0
git stash push -m "安全做法"
五、stash 最佳实践总结
| 实践 | 说明 |
|---|---|
永远加 -m 描述 | 方便后续查找和识别 |
用 push 代替 save | 更灵活,支持更多选项 |
| 用完即清 | 别攒一堆 stash 不管 |
| 大改动先 commit | stash 适合临时保存,不适合长期存档 |
跨分支用 branch 命令 | 比手动 apply 更可靠 |
写在最后
Git stash 不是"应急按钮",而是一个可以精细控制的工作流工具。
下次你再想 git stash 不加任何参数的時候,停下来想想——你真的需要描述吗?需要包含 untracked 文件吗?还是只想 stash 部分改动?
多花3秒想清楚,后面能省半小时。
觉得有用?试试在你的项目里用一次 git stash push -p,看看它怎么帮你精准选择要暂存的代码块。