git stash命令的使用
前阵子有一场面试,问到了git stash和git cherry-pick命令,面试后总觉得回答得不是很好。于是决定把这2个命令重新梳理一遍,写了这篇文章以备后续回查。
git stash的应用场景:在新建分支上进行新功能开发的时候,主分支上发现了bug,此时需要在当前分支修复完bug后,仅将修复bug的改动合并回主分支,新功能相关的代码仍然只留在当前分支。
这种场景下就可以使用git stash先暂存当前分支上的新功能代码,待把主分支需要的改动处理完并合并回去后,再将暂存的代码在当前分支上恢复回来。
我们以一个.txt文件为例,演示一次git stash的作用。
现在主分支上有一个文件test_stash.txt,并写入内容“主分支上的现有代码”:
接着开始操作,新建一个分支命名为“test_stash”,并确认已切换到test_stash分支:
1 PS D:\Project\Test\TestGitCommands> git branch test_stash 2 PS D:\Project\Test\TestGitCommands> git branch 3 * main 4 test_stash 5 PS D:\Project\Test\TestGitCommands> git checkout test_stash 6 Switched to branch 'test_stash' 7 PS D:\Project\Test\TestGitCommands> git branch 8 main 9 * test_stash
在test_stash分支上增加内容“在test_stash分支上开发新功能”:
这时候,假设主分支上发现有bug,就需要把当前test_stash分支所做的改动暂存起来,恢复到和主分支相同的状态去修改bug。于是需要执行git stash:
1 PS D:\Project\Test\TestGitCommands> git stash 2 Saved working directory and index state WIP on test_stash: 3aeb2dd 2
可以看到,执行git stash后test_stash.txt就恢复到了刚创建分支时的状态:
接下来在test_stash分支上修改bug:
修复完bug后,将改动合并回主分支:
1 PS D:\Project\Test\TestGitCommands> git branch 2 main 3 * test_stash 4 PS D:\Project\Test\TestGitCommands> git commit -a -m "bug fix" 5 [test_stash a93a69c] bug fix 6 1 file changed, 1 insertion(+), 1 deletion(-) 7 PS D:\Project\Test\TestGitCommands> git checkout main 8 Switched to branch 'main' 9 Your branch is up to date with 'origin/main'. 10 PS D:\Project\Test\TestGitCommands> git branch 11 * main 12 test_stash 13 PS D:\Project\Test\TestGitCommands> git merge test_stash 14 Updating 3aeb2dd..a93a69c 15 Fast-forward 16 test_stash.txt | 2 +- 17 1 file changed, 1 insertion(+), 1 deletion(-) 18 PS D:\Project\Test\TestGitCommands> git status 19 On branch main 20 Your branch is ahead of 'origin/main' by 2 commits. 21 (use "git push" to publish your local commits) 22 23 nothing to commit, working tree clean
可以看到,主分支上已经合并了test_stash分支修复bug的内容:
最后就可以切换回test_stash分支,把暂存的改动恢复出来。
恢复方式有2种:
一、第一种是使用git stash apply恢复,这种方式下stash列表里暂存的内容不会被删除,通过git stash list可以看到暂存的内容还在list里:
1 PS D:\Project\Test\TestGitCommands> git stash apply 2 Auto-merging test_stash.txt 3 CONFLICT (content): Merge conflict in test_stash.txt 4 On branch test_stash 5 Unmerged paths: 6 (use "git restore --staged <file>..." to unstage) 7 (use "git add <file>..." to mark resolution) 8 both modified: test_stash.txt 9 10 no changes added to commit (use "git add" and/or "git commit -a") 11 PS D:\Project\Test\TestGitCommands> git stash list 12 stash@{0}: WIP on test_stash: 3aeb2dd 2 13 stash@{1}: WIP on test_stash: 3faf7f0 add modefied file
此时test_stash.txt就把暂存的内容也合并进来了:
当然,会出现冲突,手动解决一下就好:
最后可以通过git stash drop命令删除掉stash list里的暂存内容;
二、第二种方式是使用git stash pop命令,它不仅会恢复stash list里的内容,还会把恢复的内容从stash list里删掉。
我个人更倾向于使用git stash apply,保留有转圜的余地。
最后再讨论一种更进一步的情况:假设我在test_stash分支上已经有了commit,这时候如果同样要stash改动内容后修复主分支上的bug,会发现stash是无法暂存已commit的内容的。即是stash后只能恢复到当前分支最后一次commit后的状态,无法恢复到刚新建这个分支时的状态。那么这种情况下,应该如何在test_stash分支上修复main分支上的bug,并只把修复bug的部分合并回main分支呢?我们将在下一篇讨论git cherry-pick命令来处理这个问题。

浙公网安备 33010602011771号