Git stash 高级用法:暂存、部分暂存与冲突恢复

在 Git 的日常使用中,git stash 常被视为一个简单的“临时保存”工具:手头工作没做完,突然要切分支修 bug,于是 git stash 一下,回来再 git stash pop。这个用法没错,但只发挥了它三成的能力。当遇到部分文件暂存、多次暂存管理、冲突恢复、甚至从暂存中精准提取某段代码时,git stash 的高级技巧能显著提升效率。本文将从暂存、部分暂存与冲突恢复三个维度,系统梳理 git stash 的进阶用法。

一、基础回顾:stash 到底存了什么

git stash 默认会保存两样东西:工作区中已跟踪文件的修改,以及暂存区中的内容。但它不会保存未跟踪文件(untracked files)和被忽略文件(ignored files)。这是很多人在恢复时发现“文件不见了”的根源。

一个完整的 stash 提交实际上是一个特殊的合并提交,包含工作树状态和索引状态。理解这一点,才能理解后续的 --index--staged 等选项。

常用基础命令:

git stash              # 暂存已跟踪文件的修改
git stash -u           # 同时暂存未跟踪文件
git stash -a           # 同时暂存未跟踪和忽略文件
git stash list         # 查看暂存列表
git stash pop          # 恢复并删除最近一次暂存
git stash apply        # 恢复但保留暂存记录
git stash drop         # 删除最近一次暂存

二、部分暂存:只保存你想保存的

实际开发中,我们经常同时改了好几个文件,但只想暂存其中一部分,以便先提交另一部分。git stash 提供了 -p--staged 两种精准控制方式。

1. 交互式部分暂存:git stash -p

-p--patch)会逐个代码块(hunk)询问你是否要暂存。这非常适合“一个文件里既有调试代码又有正式修改”的场景。

git stash push -p

执行后,Git 会展示每个 hunk,并给出选项:

  • y:暂存这个 hunk
  • n:不暂存
  • s:将当前 hunk 拆分成更小的 hunk
  • e:手动编辑 hunk
  • q:退出

例如,你在 app.js 中既加了 console.log 调试,又修复了一个逻辑错误。通过 -p 可以只暂存调试代码,把逻辑修复留在工作区继续提交。

2. 只暂存已 add 的内容:git stash --staged

如果你已经用 git add 把要暂存的部分放进了暂存区,可以直接:

git stash push --staged

这只会保存暂存区中的修改,工作区中未 add 的改动保持不变。这个用法在“暂存一部分、提交另一部分”的工作流中极其高效。

3. 指定文件或路径暂存

git stash push -m "修复登录逻辑" src/login.js src/auth.js

配合 -m 添加描述,避免 stash list 里全是 WIP on main 这样的默认信息。路径可以是文件、目录或通配符。

三、多次暂存的管理与精准恢复

当你有多个 stash 时,git stash list 会显示类似:

stash@{0}: On main: 修复登录逻辑
stash@{1}: On main: 调试支付流程
stash@{2}: WIP on main: 3a4b5c6 初始提交

恢复指定 stash:

git stash apply stash@{1}
git stash pop stash@{1}

applypop 的区别在于:pop 恢复后会删除该 stash,apply 则保留。在不确定是否要保留时,优先用 apply

查看 stash 内容而不恢复

git stash show stash@{1}          # 查看文件变更统计
git stash show -p stash@{1}       # 查看完整 diff

从 stash 中提取单个文件

有时你只想从某个 stash 中拿回一个文件,而不是全部恢复:

git checkout stash@{1} -- src/config.js

这会把 src/config.js 从 stash 中检出到工作区,stash 本身不受影响。这是处理“暂存里混入了不该提交的文件”时的利器。

四、冲突恢复:当 stash pop 失败时

git stash pop 最令人头疼的情况是冲突。冲突发生时,Git 会尝试合并,但不会自动删除 stash。此时工作区会留下冲突标记,stash 仍然保留在列表中。

冲突发生后的处理步骤

  1. 查看冲突文件git status 会显示 both modified 的文件。
  2. 手动解决冲突:编辑文件,保留需要的内容,删除 <<<<<<<=======>>>>>>> 标记。
  3. 标记为已解决git add <file>
  4. 不要执行 git commit:stash 恢复不是一次提交,只需 git add 后继续工作即可。
  5. 手动删除 stash:确认无误后执行 git stash drop stash@{0}

如果冲突太复杂,想放弃恢复:

git checkout -- .        # 放弃工作区修改(谨慎)
git stash apply          # 重新尝试,或换用其他方式

git stash branch 优雅解决冲突

当 stash 与当前分支差异过大时,更安全的方式是基于 stash 创建新分支:

git stash branch fix-login stash@{0}

这个命令会:

  1. 以 stash 创建时的提交为基础创建新分支 fix-login
  2. 检出该分支;
  3. 应用 stash 内容;
  4. 如果成功,自动删除该 stash。

这样冲突会在一个干净的分支上处理,不会污染当前工作区。这是处理复杂 stash 冲突的推荐做法。

五、实用技巧与注意事项

  • 给 stash 命名:始终使用 -m,例如 git stash push -m "feat: 用户头像上传"
  • stash 不是备份:stash 存在本地 .git/refs/stash 中,不会推送到远程。重要修改应及时提交到分支。
  • 避免长期堆积:stash 列表过长容易遗忘,建议每周清理一次,用 git stash list 检查。
  • popapply 的选择:不确定时用 apply,确认后再 drop
  • 恢复时保留索引状态git stash pop --index 会尝试恢复暂存区状态,适合需要保持 add 状态的场景。

结语

git stash 远不止“临时保存”一个功能。通过 -p 实现部分暂存,通过 --staged 精准控制暂存区,通过 stash@{n} 管理多次暂存,再配合 stash branch 处理冲突,你可以把工作区切换、代码审查、紧急修复等场景处理得游刃有余。下次再遇到“改到一半要切分支”的情况,不妨试试这些高级用法,让 Git 真正成为你工作流中的得力助手。

未经允许不得转载:任鹏个人博客 » Git stash 高级用法:暂存、部分暂存与冲突恢复

赞 (0) 打赏

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏