git stash 教程:从临时保存到冲突恢复
简答:先运行 git status 确认改动,再用 git stash push -m 保存未完成工作;切换分支后用 git stash list 找到记录,优先用 git stash apply 恢复并保留备份,确认无误后再 drop。未跟踪文件要加 -u,忽略文件要加 -a。
定义:git stash 是 Git 用来暂时保存工作区和暂存区未提交修改、让当前目录恢复干净状态,并在之后重新应用这些修改的命令。
先记住这条最快操作路径
如果你只是想暂时收起当前修改、切换分支处理其他工作,可以按下面顺序执行。官方文档说明,git stash 不带参数时等价于创建一次新的 stash,推荐使用带说明的 git stash push,便于之后识别。
git status
git stash push -m "暂存当前未完成工作"
git status
git switch 目标分支
# 查看已有 stash
git stash list
# 恢复最近一条,并保留 stash 记录
git stash apply stash@{0}
# 确认代码恢复无误后,再删除记录
git stash drop stash@{0}官方 Git 教程将 stash 描述为一个保存未完成修改的栈;它适合临时切换分支,不等同于正式提交,也不会随着普通 git push 自动上传到远程仓库。可参考Git 官方《贮藏与清理》。
| 目的 | 命令 | 结果 |
|---|---|---|
| 创建临时保存 | git stash push -m "说明" | 保存修改并清理工作区 |
| 查看记录 | git stash list | 按最近创建顺序列出 stash |
| 查看差异 | git stash show -p stash@{0} | 查看指定 stash 的补丁内容 |
| 恢复但保留记录 | git stash apply stash@{0} | 应用修改,不删除 stash |
| 恢复并尝试删除 | git stash pop stash@{0} | 应用修改后尝试删除 stash |
| 删除一条 | git stash drop stash@{0} | 删除指定 stash |
| 清空全部 | git stash clear | 删除所有 stash,操作前需确认 |
git stash 会保存哪些修改
默认情况下,stash 主要保存已跟踪文件的工作区修改和暂存修改。新建但尚未被 Git 跟踪的文件不会默认进入 stash;被忽略的文件也不会默认进入。需要根据文件状态选择参数。
| 文件状态 | 默认是否保存 | 需要的命令 |
|---|---|---|
| 已跟踪但未暂存的修改 | 是 | git stash push |
| 已暂存的修改 | 是,但恢复时不一定自动回到暂存区 | 恢复时加 --index |
| 未跟踪文件 | 否 | git stash push -u |
| 被忽略文件 | 否 | git stash push -a |
| 只保存部分改动 | 按交互选择 | git stash push -p |
| 只保存某个文件 | 只处理指定路径 | git stash push -- path/to/file |
-u 是 --include-untracked 的缩写,-a 是 --all 的缩写。官方文档明确区分了未跟踪文件与被忽略文件,因此不要只看到工作区变干净,就默认认为所有文件都已经保存。
如果担心遗漏,先运行:
git status --short
git stash show --stat stash@{0}需要更细地查看内容时,可以使用:
git stash show -p stash@{0}
git stash show -u -p stash@{0}命令格式和选项可在Git 官方 git-stash 文档中核对。
apply、pop、drop 到底有什么区别
最容易出错的地方是把 apply 和 pop 当成同一个命令。它们都会尝试恢复 stash,但处理 stash 记录的方式不同。
| 命令 | 是否恢复修改 | 是否删除 stash | 适合场景 |
|---|---|---|---|
apply | 是 | 否 | 第一次恢复、跨分支恢复或担心冲突 |
pop | 是 | 通常在应用成功后删除 | 确认目标分支和工作区适合直接恢复 |
drop | 否 | 是 | 确认内容已恢复或不再需要 |
clear | 否 | 删除全部 | 确认所有临时记录都不再需要 |
稳妥流程是先用 apply,检查 git status 和差异,确认结果正确后再执行 drop。使用 pop 时,如果应用过程发生冲突,Git 不一定会删除对应 stash,因此应重新运行 git stash list 核对记录,不要仅凭终端输出猜测。
如果原来的暂存状态也需要恢复,使用:
git stash apply --index stash@{0}官方教程说明,普通恢复会重新应用文件修改,但原先处于暂存区的内容不一定自动重新暂存;--index 用于尝试恢复这一状态。
切换分支、指定文件与部分改动的实战
场景一:临时切换分支
当前分支有半成品修改,但需要去处理紧急任务时:
git status
git stash push -u -m "保存当前开发中的修改"
git switch hotfix
# 处理紧急任务并完成提交
git switch 原分支
git stash list
git stash apply stash@{0}加入 -u 是为了把未跟踪文件也纳入保存范围。如果你明确不需要保存新文件,则可以省略该参数。
场景二:只保存某个文件
当工作区同时改了多个文件,但只想暂时收起其中一个,可以在命令末尾使用路径参数:
git stash push -m "暂存配置文件" -- config/app.yml路径参数前的 -- 用于区分选项和文件路径。不同 Shell 对特殊字符的处理可能不同,文件名含空格时建议使用引号。
场景三:只保存部分代码块
如果同一个文件里既有想保留的修改,也有不想暂存的修改,可以使用交互模式:
git stash push -p -m "只暂存已完成代码块"终端会逐段询问是否保存。常见选择包括保存当前代码块、不保存、退出、查看帮助等;第一次使用时应逐段确认,避免把未完成部分一起收起。
场景四:只保存已暂存内容
如果已经用 git add 标记了部分内容,只想把这些内容放进 stash,可以使用:
git stash push --staged -m "暂存已确认的修改"官方命令参考将 --staged 定义为只保存当前已经暂存的修改;如果同时使用 --patch,应以交互选择逻辑为准。
恢复时冲突怎么处理
stash 可以应用到创建它时以外的分支。如果目标分支的同一文件已经发生变化,应用时可能出现合并冲突。这不代表 stash 立即丢失,但需要按普通 Git 冲突流程处理。
- 先查看冲突文件:
git status。 - 打开冲突文件,处理
<<<<<<<<、=======、>>>>>>>标记。 - 确认内容后执行
git add 文件名,表示该文件冲突已解决。 - 再次运行
git diff --check和测试命令。 - 如果使用的是
apply,确认无误后再决定是否git stash drop。
git stash apply stash@{0}
git status
# 手动编辑冲突文件
git add path/to/conflicted-file
git diff --check
git stash list如果恢复目标不明确,或者原分支已经变化很多,可以考虑从 stash 创建新分支:
git stash branch recover-work stash@{0}该方式会尝试基于创建 stash 时的提交建立新分支,再应用对应修改,适合想把旧工作单独拿出来继续处理的情况。官方教程也将 git stash branch 列为恢复复杂 stash 的方式。
什么时候不该使用 git stash
git stash 适合短时间、临时性的工作切换,但不适合拿来长期保存重要成果。stash 默认保存在本地仓库的引用中,不能替代正式提交、远程备份或团队协作记录。
| 情况 | 更适合的方式 | 理由 |
|---|---|---|
| 只离开几分钟处理其他分支 | git stash | 快速清理工作区,稍后恢复 |
| 工作已形成可解释的阶段成果 | 临时提交 | 有提交记录,便于比较和回退 |
| 需要长期独立开发 | 新建分支 | 让工作有明确边界 |
| 需要同时维护多个工作目录 | git worktree | 减少频繁收起和恢复修改 |
| 需要团队成员接手 | 正式提交并推送 | stash 不会自动进入远程协作流程 |
如果修改已经重要到不能依赖本地临时记录,优先创建正式提交或分支。使用 git stash clear 前也要先执行 git stash list 与 git stash show -p,因为清空后不适合再把它当作常规恢复手段。
一套不容易丢代码的检查清单
- 保存前运行
git status --short,记录已修改、已暂存和未跟踪文件。 - 需要保存新文件时使用
-u,需要包含忽略文件时才使用-a。 - 创建 stash 时使用
-m写清楚任务和文件范围。 - 恢复前先运行
git stash list,不要默认最近一条就是目标记录。 - 第一次恢复优先使用
apply,确认无误后再删除。 - 恢复后运行
git status、git diff或测试命令。 - 发生冲突时先保留 stash 记录,处理并验证完成后再决定是否删除。
- 重要修改不要长期停留在 stash 中,及时转为提交、分支或其他可追踪记录。
这套流程的核心不是记住所有参数,而是始终做到“保存前确认范围、恢复后检查结果、删除前再次核对”。
常见问题
git stash 和 git commit 有什么区别?
git stash 是本地临时保存,用于快速清理工作区并稍后恢复;git commit 是正式记录,会进入项目历史。需要长期保留、分享或回退时,应优先使用提交或分支。
为什么 git stash 后新建文件还在?
因为未跟踪文件默认不会进入 stash。先用 git status 确认状态,再执行 git stash push -u;如果文件被忽略,需要使用 -a,并检查是否真的需要保存这些文件。
git stash pop 冲突后,stash 还在吗?
不能只凭命令习惯判断。冲突时先运行 git stash list 核对对应记录,再处理冲突;确认记录仍在后,不要重复执行 pop,避免再次尝试应用同一批修改。
如何恢复指定的 git stash?
先运行 git stash list,找到目标编号,例如 stash@{2},再执行 git stash apply stash@{2}。如果希望恢复原来的暂存状态,可以尝试加上 --index。
git stash apply 后如何撤销恢复的修改?
如果这些修改尚未与其他工作混合,可以先查看 git diff,再根据文件状态使用 git restore 或手动编辑。不要在没有确认范围时直接执行清理命令;重要内容应先复制或建立临时提交。
git stash clear 能恢复吗?
clear 会删除全部 stash 记录,不应当作为普通清理操作。执行前先用 git stash list 和 git stash show -p 核对;若已清空,恢复难度取决于本地对象是否仍可通过 Git 的历史对象和引用日志找到,不能保证一定恢复。
git stash save 还能不能用?
部分 Git 版本仍支持旧写法,但官方教程建议迁移到 git stash push,因为 push 支持路径限定等更明确的能力。新教程和新脚本优先使用 push。