
first-contributions 实战指南用 git stash 暂存未完成的工作并自由切换分支【免费下载链接】first-contributions✨ Help beginners to contribute to open source projects项目地址: https://gitcode.com/gh_mirrors/fi/first-contributions导读在参与开源项目例如本仓库 first-contributions的日常开发中你常常会遇到这样一个困境当前分支上有一堆未写完、未测试的改动却必须立刻切换到另一个分支处理其他事务。直接提交这些半成品违背工程规范而不提交又无法切换分支。本指南以 first-contributions 仓库的 stashing-a-file.md 为骨架完整讲解git stash的暂存、查看、恢复、删除、反向撤销与分支恢复等全部实战操作读完后你将能在不产生多余提交的前提下随时保存进度、自由切换分支并安全地在新分支上继续工作。为什么要暂存Stash切换分支前的最后一步Git 出于保护工作区的考虑默认不允许在存在未提交改动时直接切换分支。而现实中的开发节奏往往是功能还没写完、测试还没通过紧急任务却已到来。git stash正是为此设计的机制——它会把当前工作目录和暂存区中的改动记录并清空让工作区回到干净状态从而放行分支切换同时这些改动会被保存到一个后进先出LIFO的栈中随时可以完整找回。这与本仓库中 why-using-branches.md 强调的分支工作流按功能拆分分支、互不干扰天然互补分支负责隔离不同的开发线而 stash 负责在同一开发线内部临时寄存未完成的改动。查看当前改动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暂存stagedlib/simplegit.rb还停留在工作区未暂存。这两种状态在 stash 时都会被记录也会影响后续恢复的方式。保存工作进度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 masterWork In Progress表示这是一个未完成的工作条目049d078是当前分支指向的提交哈希。此时再运行git status工作区已恢复干净$ git status # On branch master nothing to commit, working directory clean现在你可以放心地git checkout/git switch到任意分支开展其他工作之前保存的改动不会丢失。查看暂存栈git stash liststash 以栈的形式保存多条记录用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 a number to logstash{0}永远指向最近一次保存的条目编号越大越旧栈的 LIFO 特性意味着stash{0}也是默认操作对象。常用参数速查参数作用git stash保存工作区与暂存区改动清空工作区git stash list列出栈中所有 stash 条目git stash apply [stash]恢复改动默认最新一条保留栈中条目git stash apply --index恢复改动同时恢复原来的暂存状态git stash pop [stash]恢复改动并删除栈中对应条目git stash drop stash仅删除栈中指定条目不恢复改动git stash show -p [stash]输出 stash 对应的补丁patch内容git stash branch 新分支名基于 stash 创建新分支并恢复改动恢复暂存的工作git stash apply 与 --index基本恢复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 apply stash-name例如git stash apply stash{1}。两个关键认知原文档特别强调不必在原分支、不必工作区干净你完全可以在 A 分支保存 stash切到 B 分支后再应用即使当前工作区还有未提交的改动也可以继续应用 stash。可能产生冲突如果当前工作区与 stash 内容无法干净合并Git 会报合并冲突merge conflict需要手工解决——具体冲突处理流程可参考仓库中的 resolving-merge-conflicts.md。恢复暂存状态--index观察上面的恢复结果index.html原本是暂存staged状态恢复后却变成了未暂存。原因在于默认的apply只恢复工作区文件内容不恢复暂存区标记。若想完整还原到保存前的状态staged 的仍 staged必须加上--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 #对比最初的git status输出可以看到index.html回到了Changes to be committedlib/simplegit.rb仍为未暂存状态——这正是保存 stash 前的完整现场。apply 与 pop 的区别git stash apply只恢复不删除条目仍保留在栈中可以反复应用多次而git stash pop在恢复最新改动后会自动从栈中删除该条目适合取一次就够了的场景$ git stash pop从栈的生命周期来看合理的使用模式是保存用git stash取出并清理用git stash pop只想复制改动到另一个分支则用git stash apply。删除暂存条目git stash drop如果某条 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)输出中的364e91f3...是这条 stash 对应的内部提交对象哈希可用于追溯或恢复误删的条目git fsck场景下的高级用法本指南不展开。撤销已应用的 Stash反向补丁与自定义别名有时你应用了 stash、做了一些工作却想撤销来自 stash 的那部分改动。Git 没有内建git unapply命令但可以用反向应用补丁实现同样的效果先用git stash show -p导出 stash 对应的补丁再用git apply -R反向应用$ git stash show -p stash{0} | git apply -R省略 stash 名称时默认取最新一条$ 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 $ #... 进行你的工作 $ git stash-unapply!前缀表示这是一个 shell 命令别名而非简单的子命令映射因此可以承载管道操作--global使其对当前用户的所有仓库生效。从 Stash 创建新分支git stash branch长时间搁置的 stash 是冲突的高发区如果你在保存 stash 后又继续修改了同一分支的文件再apply时极易触发合并冲突。更省心的方案是用git stash branch它会自动完成四步基于保存 stash 时的那个提交创建一个新分支切换到该分支应用 stash 内容应用成功则自动drop该 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)由于新分支从保存 stash 时的提交出发规避了原分支后续改动造成的冲突是安全地重拾旧工作的最短路径。stash 在真实工作流中的组合应用stash 并不是孤立命令它常与其他 Git 操作串联。仓库中的 moving-a-commit-to-a-different-branch.md 就给出了一个典型场景当你把改动提交错了分支需要把最新提交搬到正确的分支上时流程如下git reset HEAD~ --soft # 撤销最后一次提交但保留改动 git stash # 暂存这些改动 git checkout name-of-the-correct-branch # 切换到正确分支 git stash pop # 恢复改动 git add . # 重新暂存 git commit -m your message here # 在正确分支上提交这里的git stash与git stash pop恰好构成跨分支搬运未提交改动的标准组合stash负责暂时清空工作区以便切换pop负责在新分支上一次性取回并清理。配合本仓库的完整工作流你还可以这样衔接在 fork 的副本上开发时用git stash临时保存本地实验性改动再按 keeping-your-fork-synced-with-this-repository.md 的步骤同步上游同步完成后再git stash pop恢复自己的改动在多人协作修改同一个文件如本仓库的Contributors.md后想核对历史时参考 check-commit-log.md 的git log用法确认提交次序。小结stash 操作的完整决策路径你的目标使用的命令保存未完成改动并清空工作区git stash查看已保存的改动git stash list恢复改动但保留 stashgit stash apply带--index恢复暂存状态恢复改动并清理栈git stash pop丢弃某条 stashgit stash drop stash撤销已应用的 stash 改动git stash show -p \| git apply -R可做成别名在保存时的提交上新建分支并恢复git stash branch 分支名这套机制让写了一半的代码不再是切换分支的阻碍不需要制造无意义的提交不需要复制粘贴临时文件只需一次git stash改动便安全地待在栈中等你需要时再完整取回。无论是参与 first-contributions 这样的开源入门项目还是日常多分支协作开发掌握 stash 都是管理未完成工作的基本功。【免费下载链接】first-contributions✨ Help beginners to contribute to open source projects项目地址: https://gitcode.com/gh_mirrors/fi/first-contributions创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考