问题描述
1.测试场景一:假设index.html本来就在代码仓库中,现在修改了index.html页面,然后add暂存index.html页面,接着继续修改index.html页面,然后git stash,这个时候代码仓库干净了,修改被暂存,然后执行git stash pop,还原修改,这个时候发现,工作区的修改还原了,但是暂存区的修改丢失了。也就是git status发现,没有任何修改被暂存,之前暂存的修改被废弃了,但是工作区的修改完全被保留。
2.测试场景二:现在添加test01.html页面,git status显示test01.html并没有被git跟踪,然后修改index.html文件,这个时候git stash,发现index.html文件被暂存,但是test01.html文件没有被暂存。也就是git status并没有暂存没有被git跟踪的文件。
3.测试场景三:延续场景二,修改index.html文件,test01.html文件为新添文件,这个时候git add test01.html文件,让test01.html被git追踪,再git stash,通过git stash show方法可以看到test01.html文件被暂存,接着git stash pop,修改被还原,git status发现test01.html文件是被暂存状态,index.html还是被保留的工作区的修改。也就是git add 一个之前未被git追踪的文件,git stash后,这个文件会被暂存,而且git stash pop后,新添加的这个文件还是暂存状态,对比测试场景一中,index.html文件只是工作区的修改被暂存,暂存区的修改被丢失。
4.测试场景四:延续场景三,修改index.html文件,test01.html文件为新添文件,这个时候git add test01.html文件,让test01.html被git追踪,然后再修改test01.html文件,接着git stash,git stash pop,发现test01.html依然是暂存状态,但是被暂存的文件内容却是工作区最终的修改内容。也就是git add 一个之前未被git追踪的文件,然后再修改这个文件,git stash后,这个文件会被暂存,而且git stash pop后,新添加的这个文件还是暂存状态,但是暂存的修改内容却是之前工作区的修改内容而不是通过add暂存的修改内容。
通过以上测试,我没有发现git stash的工作规律,非常晕,希望git高手给我指导分析一下。
问题解答
回答1:首先,我说明一下git stash命令的基本功能:处理工作目录脏的状态,即修改的跟踪文件与暂存改动,然后将未完成的修改保存到一个栈上。知道了这些之后,我们来看看我总结的几个要点:
git stash命令会将已跟踪的文件压入栈中,而未被跟踪的文件不会被压入栈中,正如楼主的实验2中所描述的。
如果之前的工作有被添加到暂存区,git stash命令默认不会将弹出栈的那个修改再加入暂存区,正如楼主的实验1所描述的那样,但是楼主的描述其实有误,之前暂存的修改并不是被废弃或丢失而是保留在工作区,只是未加入暂存区而已。
对于楼主的实验2、3中的新添加文件test01.html,其实这算一种特殊情况吧。我们可以这样理解:stash pop的结果就是还原以前的修改,而它对于test01.html所能做的恢复操作也只能是重新加入暂存区,否则的话,test01.html将回到未被跟踪的状态。
如果想要重新应用之前暂存的修改,可以在git stash pop后加上--index选项,这样的话就可以恢复到和之前一模一样了,即之前暂存过的现在也会是暂存状态,为暂存的仍是未暂存的状态。
最后,我需要声明下楼主所说的:
之前暂存的修改被废弃了
或者
暂存区的修改被丢失
其实描述有误,或者不该这样描述,因为这样会使我们误解——我们可能会误认为git stash只会暂存工作区的修改,而实际情况应该是这样的:git stash默认会将被恢复的操作保留在工作区,但是不会自动帮你重新暂存。楼主可以重新做一下上述的实验以验证我的说法。