强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Git 完全指南 / 06 - 暂存:stash、stash pop、stash branch

第六章:暂存(Stash)

Stash 让你快速保存和恢复工作现场,是紧急切换分支时的救星。


6.1 暂存概述

当你正在开发某个功能,突然需要切换分支处理紧急 bug 时,git stash 可以快速保存当前工作区和暂存区的状态,让你的工作区恢复干净。

工作区状态 → git stash → 干净工作区 → 切换分支 → 处理任务 → 切回 → git stash pop → 恢复工作

6.2 基本操作

6.2.1 保存暂存

# 暂存已跟踪文件的修改(默认)
$ git stash

# 等价于
$ git stash push

# 暂存并添加描述信息
$ git stash push -m "正在开发登录功能"

# 暂存所有文件(包括未追踪文件)
$ git stash push -u
# 或
$ git stash push --include-untracked

# 暂存所有文件(包括忽略文件)
$ git stash push -a
# 或
$ git stash push --all

# 只暂存指定文件
$ git stash push -m "部分暂存" -- src/login.js src/auth.js

# 暂存时包含暂存区状态
$ git stash push --staged

6.2.2 查看暂存列表

# 查看暂存列表
$ git stash list
stash@{0}: WIP on main: abc1234 Add feature
stash@{1}: WIP on develop: def5678 Fix bug
stash@{2}: On main: 正在开发登录功能

# 格式化输出
$ git stash list --format="%gd: %gs (%cr)"
stash@{0}: WIP on main: abc1234 (2 minutes ago)
stash@{1}: WIP on develop: def5678 (1 hour ago)

6.2.3 恢复暂存

# 恢复最近的暂存并从列表移除
$ git stash pop
# 或
$ git stash pop stash@{0}

# 恢复暂存但保留在列表中
$ git stash apply
# 或
$ git stash apply stash@{0}

# 恢复指定的暂存
$ git stash pop stash@{2}

pop vs apply 对比:

操作恢复内容从列表移除适用场景
stash pop确认不再需要此暂存
stash apply需要多次应用同一暂存

6.2.4 删除暂存

# 删除最近的暂存
$ git stash drop

# 删除指定暂存
$ git stash drop stash@{1}

# 清除所有暂存
$ git stash clear

6.2.5 查看暂存内容

# 查看暂存的变更摘要
$ git stash show

# 查看暂存的详细差异
$ git stash show -p

# 查看指定暂存的差异
$ git stash show -p stash@{1}

# 只显示文件名
$ git stash show --name-only

6.3 高级用法

6.3.1 从暂存创建分支

当你恢复暂存时遇到冲突,可以用 stash branch 创建一个新分支来恢复:

# 基于暂存时的提交创建新分支并恢复暂存
$ git stash branch feature-from-stash
Switched to a new branch 'feature-from-stash'
On branch feature-from-stash
Changes not staged for commit:
  modified:   src/app.js

# 基于指定暂存创建分支
$ git stash branch fix-from-stash stash@{2}

💡 这是解决 stash pop 冲突的最佳方式。

6.3.2 交互式暂存

# 交互式选择要暂存的内容
$ git stash push -p

# 会像 git add -p 一样逐块询问
diff --git a/src/app.js b/src/app.js
...
Stash this hunk [y,n,q,a,d,s,e,?]?

6.3.3 保留暂存区状态

# 暂存时保留暂存区(index)的状态
$ git stash push --staged

# 恢复后暂存区状态也会恢复
$ git stash pop

6.3.4 暂存未追踪文件

# 默认只暂存已追踪文件的修改
$ git stash

# 包含未追踪的新文件
$ git stash -u

# 包含被 .gitignore 忽略的文件
$ git stash -a

# 注意:-a 包含所有文件,可能暂存不应提交的内容

6.4 暂存内部机制

暂存本质上是一个特殊的提交:

# 查看暂存的提交对象
$ git stash list --format="%H %s"
abc1234def567890 WIP on main: ghi9012 Latest commit

# 查看暂存的对象类型
$ git cat-file -t abc1234
commit

# 查看暂存的提交内容
$ git cat-file -p abc1234
tree def5678...
parent ghi9012...
author ...
committer ...

WIP on main: ghi9012 Latest commit

暂存实际创建了 2-3 个提交:

  1. 工作区提交:包含未暂存的修改
  2. 暂存区提交:包含 git add 后的内容
  3. 未追踪文件提交(如果使用 -u-a

6.5 常见问题与解决

6.5.1 Stash Pop 冲突

$ git stash pop
Auto-merging src/app.js
CONFLICT (content): Merge conflict in src/app.js
The stash entry is kept in case you need it again.

解决方法:

# 方法 1:手动解决冲突
$ vim src/app.js  # 编辑冲突
$ git add src/app.js
$ git stash drop  # 删除已应用的暂存

# 方法 2:创建新分支恢复(推荐)
$ git stash branch temp-fix-branch

6.5.2 暂存丢失恢复

如果不小心执行了 git stash clear

# 使用 fsck 查找悬空对象
$ git fsck --unreachable | grep commit
dangling commit abc1234...

# 查看悬空提交内容
$ git show abc1234

# 恢复
$ git stash apply abc1234

6.6 暂存命令速查表

命令说明
git stash暂存已跟踪文件的修改
git stash push -m "msg"暂存并添加描述
git stash -u包含未追踪文件
git stash -a包含所有文件
git stash list查看暂存列表
git stash show查看暂存摘要
git stash show -p查看暂存详细差异
git stash pop恢复并删除暂存
git stash apply恢复但保留暂存
git stash branch <name>创建分支并恢复
git stash drop删除暂存
git stash clear清除所有暂存
git stash push -p交互式暂存

业务场景

场景推荐方案
紧急切换分支修 buggit stash -u → 切分支 → 修 bug → 切回 → git stash pop
尝试不同实现git stash push -m "方案A" → 尝试方案 B → 对比选择
拉取远程更新git stashgit pullgit stash pop
保留临时实验代码git stash push -m "实验性代码" 长期保留
代码审查中途git stash → 处理其他事务 → git stash pop 继续

扩展阅读


🔗 上一章05 - 远程仓库 | 下一章07 - 历史查看