git stash命令的使用

前阵子有一场面试,问到了git stash和git cherry-pick命令,面试后总觉得回答得不是很好。于是决定把这2个命令重新梳理一遍,写了这篇文章以备后续回查。

git stash的应用场景:在新建分支上进行新功能开发的时候,主分支上发现了bug,此时需要在当前分支修复完bug后,仅将修复bug的改动合并回主分支,新功能相关的代码仍然只留在当前分支。

这种场景下就可以使用git stash先暂存当前分支上的新功能代码,待把主分支需要的改动处理完并合并回去后,再将暂存的代码在当前分支上恢复回来。

我们以一个.txt文件为例,演示一次git stash的作用。
现在主分支上有一个文件test_stash.txt,并写入内容“主分支上的现有代码”:
1

接着开始操作,新建一个分支命名为“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分支上开发新功能”:
2

这时候,假设主分支上发现有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就恢复到了刚创建分支时的状态:
1

接下来在test_stash分支上修改bug:
4

修复完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的内容:
4

最后就可以切换回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就把暂存的内容也合并进来了:
6

当然,会出现冲突,手动解决一下就好:
7

最后可以通过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命令来处理这个问题。

 

posted @ 2026-04-29 11:40  杨淳引  阅读(13)  评论(0)    收藏  举报