Git 201 - Stash Intro

很多时候,代码开发中常被打断,现行的修改不能直接被提交到版本控制器中,只希望被暂存起来,使用时将这些修改再恢复暂存时的状态。

项目开发中会经常遇到一些紧急的情况,如Hotfix,这时你需要创建新的Branch来完成这项工作,但创建分支要求先将所有修改的代码进行提交,而该部分代码并不能正常工作,不能被提交,此时能做的就是将这些修改暂存到一个地方,等Hotfix完成之后,再恢复那些修改。

另一个真实的例子是,团队成员更新了一系列文件并Commit到了Remote,而你也对其中部分文件做出修改,当使用Pull时,会发现冲突,而合并则要求你先Commit或Stash,对于已完成的代码,可以先Commit到本地,再用Pull获取,合并。但未完成的代码,就要用到Stash了。

使用Stash

在一个git工作树中,对文件作出修改,同时运行 git status,可以看到git有以下提示:

1
2
3
4
5
6
7
8
9
$ gst
# On branch feature/auth
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: config/routes.rb
#
no changes added to commit (use "git add" and/or "git commit -a")

这时,若是想切换分支,但是你还不想提交你正在进行中的工作,就可以运行 git stash命令,向 stash 栈里添加一个新的 Stash。

1
2
3
$ git stash
Saved working directory and index state WIP on feature/auth: e2c54b5 Update namespace and config
HEAD is now at e2c54b5 Update namespace and config

这时再来看目录树,里面已经是干净的了。所有的变更都被保存到e2c54b5的Stash里了。

1
2
3
$ git status
# On branch master
nothing to commit (working directory clean)

查看Stash

对于已创建的stash可以通过 git stash list来查看。

1
2
3
$ g stash list
stash@{0}: WIP on feature/auth: e2c54b5 Update namespace and config
stash@{1}: WIP on master: 76aa72b add README

因为之前已有创建过stash,所以列表里会显示有两条记录。而stash@{0}为这次所加入,因为是栈结构,所以最新加入的数字最小。

使用git stash show stash@{0} 来查看某次暂存的具体更变。

1
2
3
$ g stash show
config/routes.rb | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

还原修改

如果想将之前保存的变更重新应用回去,可以使用git statsh apply命令。默认将第一条记录恢复,可在后面使用参数来指定恢复哪次暂存git stash apply stash@{1}

1
2
3
4
5
$ g stash apply
# On branch feature/auth
# Changes not staged for commit:
#
# modified: config/routes.rb

这时,工作树里又出现了之前对代码所做出的修改。当然,你可以将这个stash应用到不同的分支,如果这个分支在Stash之后做出过修改,也是可以应用的。stash会对冲突进行合并。

删除Stash

使用 Apply 并不会移除 Stash 队列中的记录,而需要通过git stash drop 来进行删除,可以通过 stash@{0} 的参数来删除指定记录。

git stash pop 则是 apply + drop,在应用完变更后立即删除 stash 记录。

撤销Stash的恢复

如果不小心恢复错了某一版本的stash,还可以通过git stash show -p | git apply -R,如果恢复了多个版本,可以通过 git stash show -p stash@{0} | git apply -R 参数来指定移除某次的恢复记录。

从Stash记录中创建 Branch

如果当前 Branch 已经做出很多修改,而只想看下某次变更的效果,直接 apply 的话,要合并冲突,成本太大。可以直接使用 git stash branch name stash@{0} 命令,将创建一个新的分支,指向到你该次 stash 所处的状态。很方便的查看 stash 改变。