news 2026/9/18 7:02:05

first-contributions 进阶指南:用 Git Stash 暂存工作进度,安全切换分支不丢代码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
first-contributions 进阶指南:用 Git Stash 暂存工作进度,安全切换分支不丢代码

first-contributions 进阶指南:用 Git Stash 暂存工作进度,安全切换分支不丢代码

【免费下载链接】first-contributions🚀✨ Help beginners to contribute to open source projects项目地址: https://gitcode.com/gh_mirrors/fi/first-contributions

本文是 first-contributions 开源贡献入门仓库 docs/additional-material/git_workflow_scenarios/stashing-a-file.md 及其多语言版本(如 白俄罗斯语译文、简体中文译文)的技术导读。当你完成仓库 README.md 中的 fork → clone → 修改 → 提 PR 基本流程后,在真实协作场景中会频繁遇到"代码写一半却要切换分支"的困境,本文的git stash系列命令就是解决这一问题的标准答案。读完本文,你将掌握git stashgit stash listgit stash applygit stash popgit stash dropgit stash branch的完整用法,以及用反向补丁"撤销应用"与自定义 Git 别名的进阶技巧。

问题场景:未提交的更改挡住了切换分支

假设你在一个大型代码项目中工作,正在master分支上修改代码,突然需要切换到另一个分支处理紧急任务。此时代码尚未写完、也没有配套测试,你大概率不想提交这些不完整、可能无法通过 CI 的更改。但 Git 的分支切换机制要求工作区保持整洁,否则不允许你直接切换,以免破坏开发流。

怎么办?既避免一次多余的 commit,又能自由跳转分支?这正是git stash(暂存/搁置)机制要解决的问题。它相当于把当前工作区"存档"到一个栈中,还你一个干净的工作目录,等你需要时再恢复。

在深入命令之前,先建立与仓库其他进阶文档的关联认知:

  • additional-material 索引 列出了本仓库全部进阶 Git 主题(修改提交、配置 Git、保持 fork 同步、移除文件、删除分支、解决合并冲突、revert、squash、撤销本地提交等),stash 教程正是其中之一;
  • 为什么需要频繁切换分支,可参考 为什么使用分支:分支让多人、多特性并行开发而不互相干扰,切换分支因此成为日常操作,stash 则是切换时的"安全气囊"。

暂存你的工作(Stashing)

第一步:用 git status 确认当前更改

假设你在项目某个分支上修改了若干文件。运行git status,可以看到更改的分布情况:

$ git status # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: index.html # # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # # modified: lib/simplegit.rb #

注意输出里有两类更改:index.html已经git add进入暂存区(index/staging area)lib/simplegit.rb还停留在工作区(working directory)git stash默认会同时保存这两类更改,这也是后面--index参数存在的意义。

第二步:git stash 压栈保存

现在你想切换分支,但暂时不想提交任何更改,于是执行git stash,把当前改动推入一个"stash 栈":

$ git stash Saved working directory and index state \ "WIP on master: 049d078 added the index file" HEAD is now at 049d078 added the index file (To restore them type "git stash apply")

输出中的WIP on master: 049d078 added the index file表示:这是master分支上基于提交049d078的"工作进行中(Work In Progress)"状态。Git 会提示你用git stash apply来恢复。

此时再次运行git status,工作目录已经干净:

$ git status # On branch master nothing to commit, working directory clean

第三步:git stash list 查看栈中所有存档

现在你可以切换到任意分支继续工作,stash 的内容以**栈(stack)**的形式保存在本地。使用git stash list查看栈中已有哪些存档:

$ git stash list stash@{0}: WIP on master: 049d078 added the index file stash@{1}: WIP on master: c264051 Revert "added file_size" stash@{2}: WIP on master: 21d80a5 added number to log

每个条目以stash@{编号}标识,stash@{0}永远是最近一次 stash。注意输出格式与git reflog相似,底层上都对应本地引用(ref),git stash系列命令正是围绕这些引用操作(例如后文git stash branch输出中的Dropped refs/stash@{0})。

第四步:git stash apply 恢复更改

想重新应用刚才保存的更改,使用git stash apply。默认恢复最近一次的 stash:

$ git stash apply # On branch master # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # # modified: index.html # modified: lib/simplegit.rb #

可以看到,Git 重新改回了你在保存 stash 时未提交的文件。如果想应用栈中其他条目,可以显式指定名称:

git stash apply <stash-name>

<stash-name>替换为具体的条目名,例如git stash apply stash@{1}

两个重要事实(原文档特别强调):

  1. 本示例中,你是在干净的工作目录下、在保存 stash 的同一分支上应用 stash,但这两种条件都不是必须的。你完全可以在 A 分支保存 stash、切到 B 分支后再应用;即使应用时工作目录存在未提交更改也可以,只是如果某些内容无法干净地应用,Git 会抛出合并冲突(merge conflict),需要按 解决合并冲突 的流程手工处理——冲突标记、git add标记已解决、再git commit
  2. git stash apply恢复的是文件内容,但不会恢复暂存状态。对比上面的输出会发现:index.html在保存前是 staged(Changes to be committed),应用后却变成了 unstaged。要让暂存状态一并恢复,需要加--index参数:
$ git stash apply --index # On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: index.html # # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # # modified: lib/simplegit.rb #

加上--index后,输出与 stash 之前完全一致:index.html回到暂存区,lib/simplegit.rb保持未暂存——你回到了"原来的位置"。

第五步:git stash drop 与 git stash pop

apply只负责应用,stash 条目仍保留在栈中(方便反复应用)。想从栈中删除某个条目,用git stash drop并指定名称:

$ git stash list stash@{0}: WIP on master: 049d078 added the index file stash@{1}: WIP on master: c264051 Revert "added file_size" stash@{2}: WIP on master: 21d80a5 added number to log $ git stash drop stash@{0} Dropped stash@{0} (364e91f3f268f0900bc3ee613f9f733e82aaed43)

输出末尾的364e91f3f268f0900bc3ee613f9f733e82aaed43是这条 stash 对应的提交对象哈希,可作为审计依据。

如果你希望"应用最近一次 stash并同时从栈中删除",可以用git stash pop——它等价于git stash apply+git stash drop的组合,是最常见的恢复用法:

git stash pop

取消应用已应用的 Stash(Un-applying)

有些场景下,你应用了 stash、做了一些工作,但之后想撤销那些原本来自 stash 的更改。Git 并没有内建的git unapply命令,但可以通过"取出 stash 对应的补丁,再反向应用"来实现:

$ git stash show -p stash@{0} | git apply -R

命令拆解:

  • git stash show -p stash@{0}:以补丁(patch)形式显示stash@{0}的完整差异;
  • git apply -R:将补丁**反向(Reverse)**应用到当前工作区,等于把 stash 带来的更改逐行回滚。

同样地,不指定 stash 名称时 Git 默认取最新一条:

$ git stash show -p | git apply -R

由于这条组合命令较长,原文档推荐把它配置成 Git 全局别名,等效于新增一个stash-unapply子命令:

$ git config --global alias.stash-unapply '!git stash show -p | git apply -R' $ git stash apply $ #... work work work $ git stash-unapply

注意别名值开头的!表示这是一条Shell 命令而非普通 Git 子命令,Git 会交给 shell 执行整段管道。之后每次需要"撤销 stash 应用"时,直接敲git stash-unapply即可。

从 Stash 创建新分支

最后一个常见困境:你把某份工作 stash 后搁置了一段时间,又在原分支上继续开发。当你想重新应用这份 stash 时,如果apply试图修改的文件已经被后续开发改过,就会产生合并冲突,需要手工解决,很麻烦。

更省事的方式是用git stash branch:它会自动完成四件事——①创建一个新分支;②检出你当时 stash 工作所处的那个提交;③在该提交上重新应用 stash 内容;④如果应用成功,自动丢弃这条 stash。

$ git stash branch testchanges Switched to a new branch "testchanges" # On branch testchanges # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: index.html # # Changes not staged for commit: # (use "git add <file>..." to update what will be committed) # # modified: lib/simplegit.rb # Dropped refs/stash@{0} (f0dfc4d5dc332d1cee34a634182e168c4efc3359)

输出末尾的Dropped refs/stash@{0}印证了"应用成功即自动删除"的行为。由于新分支是基于 stash 时的旧提交创建的,与当前分支的后续改动完全隔离,通常能避免冲突;而暂存状态(index.html已 staged)也会一并保留。这是"轻松恢复被 stash 的工作并在新分支上继续开发"的绝佳捷径——非常适合在开源贡献场景中把搁置的试验性改动单独拉出来验证。

实战小结:把 stash 融入日常贡献工作流

结合 first-contributions 仓库的整套进阶材料,可以梳理出 stash 在真实贡献流程中的定位:

场景推荐命令效果
切换分支前保存未提交改动git stash工作区变干净,改动入栈
查看已保存的改动git stash liststash@{n}列出
恢复最近改动(保留栈内条目)git stash apply只应用,不删除
恢复改动并还原暂存状态git stash apply --index暂存区/工作区都还原
恢复最近改动并出栈git stash pop应用后自动删除该条目
删除指定条目git stash drop stash@{n}手动清理栈
撤销已应用的 stash 改动git stash show -p \| git apply -R反向补丁回滚
从 stash 开辟新分支继续开发git stash branch <name>建分支 + 应用 + 自动删除

需要提醒的边界与注意事项:

  • git stash默认只暂存已跟踪文件的改动,新建但从未git add过的文件默认不会被包含(可结合git add -ugit stash -u处理未跟踪文件,视实际需求取舍);
  • stash 保存在本地,不会随git push上传,跨机器恢复需要自行处理;
  • 若在应用 stash 时遭遇冲突,参照 解决合并冲突 的标记识别、git addgit commit流程解决;
  • stash 与分支、reset 等操作组合使用时,建议先git stash list确认栈内容再执行删除类命令,避免误丢工作;
  • 频繁切换分支与保持分支同步也是协作常态,可配合 保持 fork 与上游同步 与 撤销本地提交 一起学习,形成完整的本地仓库管理能力。

原文档英文版位于 stashing-a-file.md,并已翻译为 白俄罗斯语、简体中文、斯洛文尼亚语、土耳其语 等多个语言版本,读者可按需对照阅读。掌握 stash,你就能在开源协作中从容应对"代码写一半就要切换分支"的高频场景,不丢一行代码。

【免费下载链接】first-contributions🚀✨ Help beginners to contribute to open source projects项目地址: https://gitcode.com/gh_mirrors/fi/first-contributions

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 6:58:45

Ka波段功放直通模式通孔电容降低功合器插损

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 6:58:41

RFM6601与LoRaWAN实战:远距离低功耗大容量的部署与调优

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 6:58:11

数据治理落地方案:元数据、数据质量与主数据管理实战

简介&#xff1a;针对企业普遍面临的数据孤岛、数据标准缺失与质量参差不齐等问题&#xff0c;这份《数据治理服务解决方案》以35页Word文档完整呈现数据治理从规划到落地的实施路径。内容按“概述与目标—需求分析—体系建设—治理应用—附录制度”组织&#xff0c;覆盖管控机…

作者头像 李华
网站建设 2026/9/18 6:56:09

CANN ATVOSS 算子开发指南:PlaceHolderTmpLike 临时对象占位符详解

CANN ATVOSS 算子开发指南&#xff1a;PlaceHolderTmpLike 临时对象占位符详解 【免费下载链接】atvoss ATVOSS&#xff08;Ascend C Templates for Vector Operator Subroutines&#xff09;是一套基于Ascend C开发的Vector算子库&#xff0c;致力于为昇腾硬件上的Vector类融合…

作者头像 李华
网站建设 2026/9/18 6:55:02

医学图像配准形变场可视化:从位移场到雅可比折叠检测

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华