Git-Stash

为了简化本地测试代码的过程,往往会对一些代码/配置进行修改。例如设置日志级别,开启Bean的懒加载,关闭一些不必要的服务。这些修改只发生在本地工作区(Working Directory),不会commit本地仓库(Repository),更不会push远程仓库(Remote repositories)。由于在IDEA中,默认没有启用暂存区(Staging Area/Index),因此主要讨论的是工作区仓库

工作区存在一些未commit的修改,并需要checkout到别的分支,并且这个分支也对被修改的文件做了其他修改,就会导致冲突(conflict)发生。

如果在IDEA中,发生了这样的冲突,则会不允许checkout。检查IDEA中的git console,错误信息如下:

1
2
3
4
error: Your local changes to the following files would be overwritten by checkout:
SomeFile.txt
Please commit your changes or stash them before you switch branches.
Aborting

提示也十分明确,解决方法包括commitstash。接下来就具体说明每一种方式是怎么解决的。

commit

前面提到,这些修改本身是不想commit的,因为下次push时会默认将这个commit推送到远程仓库。实际情况中不会选择这种方案。

commit之后,工作区本地仓库就保持一致了,不存在未保存的信息。此时checkout到别的分支时没有任何报错。从别的分支再返回时,也能恢复这部分工作区修改。

如果需要在别的分支上也应用这部分修改,那么就需要合并分支,也就是mergerebase。由于两个分支存在冲突,在合并时会需要先解决冲突。但这样做,在两个分支上都会有这部分修改的commit。

stash

stash是一个git命令,通过stash指令,可以将未提交的工作区暂存区中的修改保存起来,并恢复到上一次commit的状态,像是将工作区reset --hard到了HEAD所指的版本。但修改部分的内容并没有丢失,像是有一个隐藏的临时commit。由于此时工作区本地仓库保持一致,checkout到别的分支不会有任何问题。

在下次checkout回此分支时,可以通过git stash pop工作区还原回之前的状态。像是reset回了之前的隐藏临时commit。如果在别的分支使用git stash pop,那么会发生冲突,但不会因此产生合并的commit

IDEA Shelve

IDEA提供了一个功能上和stash几乎一样的Shelve。略微有些区别是stash默认操作整个工作区,而Shelve可以通过GUI选择单个文件或ChangelistChangelistIDEA提供的将未提交修改分组的功能。

总结

只有在工作区暂存区版本库一致时,也就是working tree clean时,才能checkout到别的分支。我们使用的IDE可以自动stashShelve,使得这三者不一致时也能checkout。但如果发生冲突,就需要手动解决冲突

对于一些便于测试的代码/配置修改,相较于commit更推荐stashShelve。如果使用的是IDEA,那么更推荐Shelve,因为其提供了GUI,并且可以方便地指定暂存部分修改。


Git-Stash
http://dracoyus.github.io/2023/04/19/Git-Stash/
作者
DracoYu
发布于
2023年4月19日
许可协议