git stash
不知道使用git的同学有没有遇到这种情况:在当前分支下修改了一些代码,还未来的急提交(commit),但是遇到紧急情况,需要切换到另外一个分支上工作。这时候如果强行进行切换的话还出现什么情况呢?我们来举个例子演示一下:
1.新建一个目录git-test,初始化一下仓库,做一次简单的提交:
mkdir git-test
cd git-test/
git init
echo 0 > test
git add .
git commit -am "init"
2.新建一个分支:
git checkout -b master1
简单地修改test文件:
linux-geek:/home/tmp/git-test # echo 1 >> test
linux-geek:/home/tmp/git-test # cat test
0
1
我们用git status看一下:
linux-geek:/home/tmp/git-test # git status
# On branch master1
# 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: test
#
no changes added to commit (use "git add" and/or "git commit -a")
如果这个时候我们有紧急情况要处理需要切换到分支master上,但是此时分支master1的改动我们并不想立即提交,该怎么办呢?如果此时我们强行切换到分支master上,如下:
linux-geek:/home/tmp/git-test # git checkout master
M test
Switched to branch 'master'
linux-geek:/home/tmp/git-test # cat test
0
1
在分支master1上的修改会被强制应用到分支master上,这是我们所不想发生的事情。那这时我们该怎么处理呢?这个时候git stash就派上用场了。我们回到第2步切换分支之前。
3.这时候如果我们直接敲入命令git stash,会发生什么呢?
linux-geek:/home/tmp/git-test # git stash
Saved working directory and index state WIP on master1: 5c28393 init
HEAD is now at 5c28393 init
再来用git status看一下:
linux-geek:/home/tmp/git-test # git status
# On branch master1
nothing to commit (working directory clean)
linux-geek:/home/tmp/git-test # cat test
0
发现工作目录是干净的,我们把在分支master1的一些改动暂存起来了。这时候我们切换到分支master是安全的,没有任何问题的。
4.好了,假设我们在分支master上的工作完成了,并且也提交了,我们又回到了分支master1上,想要应用之前的改动该怎么办呢?我们可以用一系列的命令来实现这个功能:
4.1 我们先来git stash list来看一下我们的暂存区里面有哪些存贮的东西:
linux-geek:/home/tmp/git-test # git stash list
stash@{0}: WIP on master1: 5c28393 init
现在,我们只有一个提交,那我们直接git stash apply看一下:
linux-geek:/home/tmp/git-test # git stash apply
# On branch master1
# 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: test
#
no changes added to commit (use "git add" and/or "git commit -a")
linux-geek:/home/tmp/git-test # cat test
0
1
直接git stash apply会挑选最近一次git stash(stash@{0})的内容加以应用。如果我们之前有好几次git stash(注意:每一次git stash都会做一次压栈处理),在这里我们可以挑选一个stash加以应用:
linux-geek:/home/tmp/git-test # git stash list
stash@{0}: WIP on master1: 5c28393 init
stash@{1}: WIP on master1: 5c28393 init
linux-geek:/home/tmp/git-test # git stash apply stash@{1}
# On branch master1
# 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: test
#
no changes added to commit (use "git add" and/or "git commit -a")
如果我们直接git stash pop会出现什么情况呢?
linux-geek:/home/tmp/git-test # git stash pop
# On branch master1
# 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: test
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (34972248ca71c1e4cf2b5937398649dfcb3c00b5)
linux-geek:/home/tmp/git-test # cat test
0
2
linux-geek:/home/tmp/git-test # git stash list
stash@{0}: WIP on master1: 5c28393 init
你会发现stash@{1}不见了。其实不然,实际上是做了个这样的处理:把stash@{0}出栈,把原来的stash@{1}替换stash@{0},所以stash@{1}并没有消失,只不过换了个名字而已。
如果我们不想要栈存里面的某一个stash,我们可以直接git stash drop掉:
linux-geek:/home/tmp/git-test # git stash list
stash@{0}: WIP on master1: 5c28393 init
linux-geek:/home/tmp/git-test # git stash drop stash@{0}
Dropped stash@{0} (cde55b11b448d1ecd8ca0751bad6b9f10f878100)
linux-geek:/home/tmp/git-test # git stash list
我们会发现此时,栈空了。如果我们想更彻底些,直接把所有的stash扔掉,可以直接git stash clear。