
这篇文章把Stash的基本用法拆成了新手能轻松看懂的步骤:从用git stash
一键保存当前工作区,到git stash list
查看所有暂存记录,再到git stash apply
/pop
恢复指定版本,最后用git stash drop
/clear
清理无用缓存——每一步都配了具体场景(比如“保存后切分支改bug”“恢复时选特定版本”)和操作示例,甚至连“stash会存哪些内容”“恢复后要不要删记录”这种细节都讲到位了。不管是第一次用Stash,还是之前用过但总记混命令,跟着这篇走,都能快速搞定“临时存代码”的问题,再也不用为“中途切换”慌慌张张啦!
你有没有过这种情况?写了一半的代码还没调通——比如刚给用户中心加了个验证码功能,前端还没对接,这时候产品突然发消息说“线上商品详情页加载慢,赶紧修!”。这时候你慌不慌?直接切分支吧,未完成的验证码代码会跟着跑,万一改bug的时候不小心覆盖了怎么办?提交半成品吧,commit记录里留个“临时保存”的记录,以后翻日志的时候看着都闹心。别慌,这时候Git里有个专门解决“临时存代码”的工具——Git Stash,简直是救急的“代码暂存箱”。
Git Stash到底是啥?先搞懂它的“暂存逻辑”
我第一次听说Stash的时候,以为它和commit差不多,都是存代码——结果用的时候才发现完全不是。Git Stash的核心是“暂存当前工作区和暂存区的修改,但不生成commit记录”。 它就像你电脑里的“临时文件夹”,把你正在写的东西先塞进去,等你处理完紧急的事,再拿出来继续写。
但要注意啊,Git Stash默认只存“已跟踪文件”的修改——什么是已跟踪文件?就是已经被Git记录过的文件,比如你之前add过的user.js
。如果是新建的、还没add的文件(比如刚建的test.js
),默认不会存进去。我第一次踩坑就是这样:上次帮朋友改他的个人博客代码,新建了一个contact.html
,还没add,用git stash
存了之后切分支,结果回来发现contact.html
不见了,以为Git出问题了——后来查了Git官方文档(https://git-scm.com/docs/git-stashnofollow)才知道,默认情况下Stash不处理未跟踪文件,得加个-u
参数(或者include-untracked
)才行,比如git stash -u
,这样新建的文件也能存进去。
为什么Git要这么设计?其实是为了避免存一些没用的文件——比如你可能会新建一些临时日志文件或者编译产物,这些文件本来就不在Git的版本控制里,Stash默认不存它们,是怕帮你存了一堆垃圾,反而给你添乱。
再举个例子,假设你正在master
分支写代码,修改了user.js
(已跟踪文件),新建了utils.js
(未跟踪文件)。这时候用git stash
存,只会存user.js
的修改;如果用git stash -u
,会存user.js
的修改和utils.js
;如果用git stash -a
(all
),连.gitignore
里的文件(比如node_modules
)都会存,但一般不 用-a
,因为忽略的文件都是不需要版本控制的,存进去反而占空间。
还有个小细节要注意:Stash不仅会存工作区的修改,还会存暂存区的修改。比如你已经用git add
把user.js
的修改放到暂存区了,这时候用git stash
,暂存区的内容也会被存进去——恢复的时候,暂存区的状态也会跟着恢复。我之前不知道这一点,以为Stash只存工作区的修改,结果恢复的时候发现暂存区的内容也回来了,当时还愣了一下,后来查文档才明白,Stash是“完整暂存当前状态”,包括工作区和暂存区。
Git Stash的核心用法:从“存”到“取”的完整流程
既然搞懂了Stash的逻辑,接下来咱们一步步讲怎么用——从“存”代码到“取”代码,再到“清理”暂存记录,全流程都给你掰碎了讲。
第一步:用git stash
把代码“塞”进暂存箱
存代码的基本命令是git stash
,但我 你一定要加注释——比如git stash save "修复验证码功能到一半"
。为什么要加注释?因为等你存了多个Stash之后,用git stash list
看的时候,能一眼分清哪个是哪个。我之前帮同事解决问题,他存了三个Stash,结果list出来全是“WIP on master”(WIP是Work In Progress的缩写,意思是“正在进行的工作”),根本分不清哪个是哪个,后来我教他用save
加注释,比如“2024-05-20暂存用户中心修改”,之后找起来就方便多了。
比如你现在在master
分支,修改了user.js
,要存起来:
git stash save "用户中心验证码功能未完成"
执行完这句话,Git会提示你Saved working directory and index state On master: 用户中心验证码功能未完成
,这时候你的工作区就会回到修改前的状态——也就是说,user.js
的修改被暂存起来了,工作区里的user.js
变成了最后一次commit的版本。
如果你想存未跟踪文件,就加-u
参数:
git stash save -u "用户中心:新建utils.js未完成"
这样新建的utils.js
也会被存进去——我现在每次存Stash都会习惯性加-u
,就怕漏存文件。
第二步:用git stash list
看“暂存箱”里有啥
存完之后,怎么看存了哪些内容?用git stash list
命令。执行之后,你会看到类似这样的输出:
stash@{0}: On master: 用户中心验证码功能未完成
stash@{1}: On feature/pay: 支付模块调试中
stash@{2}: On dev: 商品列表优化
这里的stash@{0}
是最新存的Stash,stash@{1}
是上一个,依此类推。每个记录后面的注释就是你存的时候写的,所以注释一定要写清楚具体内容——比如“用户中心验证码功能未完成”比“临时保存”好一百倍,后者根本记不住是什么内容。
我还有个小技巧:如果Stash记录太多,用git stash list pretty=oneline
可以简化输出,只显示每条Stash的简要信息,看起来更清爽。比如:
stash@{0} 3a1b2c3 On master: 用户中心验证码功能未完成
stash@{1} 4d5e6f7 On feature/pay: 支付模块调试中
这样连Stash的哈希值都能看到,更方便定位。
第三步:恢复Stash——apply
和pop
的区别要分清
等你处理完紧急的事,要继续写之前的代码了,这时候需要把Stash里的内容恢复回来。恢复有两个命令:git stash apply
和git stash pop
,区别很大,一定要搞清楚。
先讲git stash apply
:这个命令会把Stash里的内容恢复到当前工作区,但不会删除Stash记录。比如你要恢复最新的Stash,就用git stash apply
;如果要恢复指定的Stash(比如stash@{1}
),就用git stash apply stash@{1}
。为什么要用apply
?比如你不确定恢复后会不会有冲突,先apply
试试,等确认没问题了,再用git stash drop stash@{1}
把这个Stash记录删掉——这样更安全,避免恢复错了还找不回原记录。
再讲git stash pop
:这个命令会恢复Stash内容,并且直接删除对应的Stash记录。比如git stash pop stash@{0}
,恢复之后,stash@{0}
就从list里消失了。如果你肯定恢复后不需要再保留这个Stash记录,用pop
更方便,省一步删除的操作。
我举个自己的踩坑例子:去年帮朋友改他的电商网站代码,他存了个Stash叫“购物车功能未完成”。我处理完紧急问题回来,直接用git stash pop
恢复——结果发现购物车的代码和他刚改的订单模块有冲突(都改了cart.js
的calculateTotal
函数)。这时候我慌了,因为pop
已经把Stash记录删了,万一冲突解决不了,我连原Stash都找不回来——幸好最后冲突解决了,但从那以后,我恢复Stash的时候都先用apply
,确认没问题再删记录。
再讲冲突的解决办法:如果恢复的时候Git提示冲突(比如Auto-merging cart.js
然后CONFLICT (content): Merge conflict in cart.js
),你需要手动解决冲突——就像合并分支一样。打开冲突的文件,你会看到类似这样的内容:
<<<<<<< Updated upstream
function calculateTotal(items) {
return items.reduce((sum, item) => sum + item.price item.quantity, 0);
}
=======
function calculateTotal(items) {
const sum = items.reduce((sum, item) => sum + item.price item.quantity, 0);
return sum * 0.9; // 加了9折优惠
}
>>>>>>> Stashed changes
左边<<<<<<< Updated upstream
是当前分支的代码(你处理紧急问题时改的),右边>>>>>>> Stashed changes
是Stash里的代码(你之前存的)。你需要做的是:
<<<<<<<
、=======
、>>>>>>>
);git add cart.js
;git commit
提交解决冲突后的代码。解决冲突的过程可能有点麻烦,但只要你懂合并分支的操作,就没问题——其实Stash的恢复本质上就是把Stash里的修改“合并”到当前分支。
第四步:清理Stash——别让“暂存箱”变“垃圾堆”
存得多了,Stash列表会越来越长,找起来麻烦,所以定期清理很重要。清理有两个命令:git stash drop
和git stash clear
,用法不一样。
git stash drop
是删除指定的Stash记录,比如你要删stash@{2}
,就用git stash drop stash@{2}
。我一般每周都会用git stash list
看看,把那些“已经完成任务、不需要再恢复”的Stash删掉——比如上个月存的“商品列表优化”,现在功能已经上线了,肯定不需要了,就删掉。
git stash clear
是删除所有Stash记录,比如你觉得列表里的Stash都没用了,就用这个命令——但要注意啊,删了之后就找不回来了,所以用之前一定要确认清楚。我一般不用clear
,除非我换了个新项目,之前的Stash肯定用不上了,才会用。
给你个清理的小技巧:用git stash list
查看记录时,把没用的Stash记下来,比如stash@{0}
、stash@{2}
,然后用git stash drop stash@{0}
和git stash drop stash@{2}
删掉——这样比clear
更精准,不会误删有用的Stash。
为了让你更清楚,我做了个Git Stash常用命令对照表,你可以存下来,用的时候对照着看:
命令 | 作用 | 适用场景 |
---|---|---|
git stash save “注释” | 暂存已跟踪文件的修改 | 需要临时切换分支处理紧急问题 |
git stash save -u “注释” | 暂存已跟踪+未跟踪文件的修改 | 有新建文件需要暂存 |
git stash list | 查看所有暂存记录 | 找特定的Stash版本 |
git stash apply stash@{n} | 恢复Stash内容,不删除记录 | 不确定是否保留Stash记录 |
git stash pop stash@{n} | 恢复Stash内容,删除记录 | 确认不需要再保留Stash记录 |
git stash drop stash@{n} | 删除指定的Stash记录 | 清理单个无用的Stash |
git stash clear | 删除所有Stash记录 | 批量清理所有无用的Stash |
最后再给你提几个新手必看的避坑 :
feature/unfinished
)或者commit(可以加amend
修改commit信息),别用Stash;.env
文件)里,并且把.env
加到.gitignore
里;git stash show -p stash@{0} > stash0.patch
把Stash导出成.patch文件,存到本地——万一Stash记录丢了,还能通过.patch文件恢复。其实Git Stash的用法真的很简单,只要你搞懂“暂存-查看-恢复-清理”的流程,就能轻松解决“临时存代码”的问题。我现在写代码的时候,几乎每天都要用Stash——比如切分支修bug、同步远程代码、帮同事排查问题,都靠它救急。
你有没有用过Git Stash?遇到过什么问题?欢迎在评论区告诉我,我帮你看看——毕竟踩过的坑多了,总能帮你避几个。
Git Stash和Git Commit有什么不一样?
Git Stash是“临时暂存”,存的是还没完成的修改,不会生成commit记录,适合临时切换任务;而Git Commit是“正式保存”,会把修改固定成版本记录,以后能追溯。简单说,Stash像“临时文件夹”,Commit像“归档文件”——你不会把没写完的草稿直接归档,但会先放临时文件夹里。
比如你写了一半的验证码功能,用Stash存起来,工作区会回到修改前的状态,等处理完bug再恢复;如果用Commit,就得写个“临时保存”的备注,以后翻commit日志会很混乱。
为什么我用Git Stash存了代码,新建的文件不见了?
因为Git Stash默认只存“已跟踪文件”(就是之前add过的文件),新建的、还没add的“未跟踪文件”不会自动存。比如你新建了utils.js还没add,直接用git stash存,这个文件就不会进暂存箱,切分支后自然看不到。
解决办法很简单——存的时候加个-u参数,比如git stash save -u “新建utils.js未完成”,这样未跟踪文件也能存进去。我现在存Stash都会习惯性加-u,就怕漏存新建的文件。
git stash apply和git stash pop该选哪个?
核心区别是“会不会删Stash记录”:apply恢复后,Stash记录还在,适合你不确定要不要保留的情况;pop恢复后,记录直接删掉,适合你肯定不用再存的情况。
比如你恢复验证码功能的Stash,先用apply试试——如果恢复后没冲突,确认没问题了,再用git stash drop删掉记录;如果直接用pop,恢复后记录没了,万一冲突没解决,想找回原记录都难。我之前踩过pop的坑,现在都先用apply。
存了好几个Git Stash,怎么找到我要的那个?
用git stash list命令就行,会列出所有暂存记录,比如stash@{0}是最新存的,stash@{1}是上一个,后面的注释就是你存的时候写的。注释一定要写清楚,比如“用户中心验证码未完成”比“临时存”好用一百倍——不然你根本分不清哪个是哪个。
要是记录太多,还能加pretty=oneline简化输出,连Stash的哈希值都能看到,找起来更准。比如git stash list pretty=oneline,输出会更清爽。