GitStash
# 80.Git-stash
stash 可以冻结目前的状态
# 在 git stash 出现之前
当我们在开发一个新功能的时候,突然来了一个紧急的 bug 要修复,此时我们可以创建一个分支去修复它;但如果,切换会导致冲突的话,就会切换失败。
我们来模拟下(先确保工作区是干净的):
$ git branch bug02
$ echo "test" >> 3-branch/branch.txt
$ cat 3-branch/branch.txt
Creating a new branch is quick and simple
test no fast forward
test
$ git add .
$ git commit -m "add test to branch.txt"
2
3
4
5
6
7
8
9
10
11
12
13
接下来,我们切换并修改 branch.txt 的最后一行,使得其和 master 分支不一样:
$ git switch bug02
Switched to branch 'bug02'
$ vim 3-branch/branch.txt
$ cat 3-branch/branch.txt
Creating a new branch is quick and simple
test no fast forward
fuk
2
3
4
5
6
7
8
9
接下来我们切换,果然,报错了:
$ git switch master
error: Your local changes to the following files would be overwritten by checkout:
3-branch/branch.txt
Please commit your changes or stash them before you switch branches.
Aborting
2
3
4
5
Git 告诉我们可以提交后再切换;但是我们目前仅仅开发到一半,不想提交,怎么办?
# Git stash 演示
Git 提供了 stash 功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:
$ git stash
Saved working directory and index state WIP on bug02: a2f5dc9 rm temp.txt
2
现在,用 git status
查看工作区,就是干净的(除非有没有被 Git 管理的文件),因此可以放心地切换分支。
$ git status
On branch bug02
nothing to commit, working tree clean
$ cat 3-branch/branch.txt
Creating a new branch is quick and simple
test no fast forward
2
3
4
5
6
7
等后续修复完 bug 后,如何恢复现场呢?首先,我们的工作现场是存储在一个栈里的,我们可以查看当前有哪些工作现场:
$ git stash list
stash@{0}: WIP on bug02: a2f5dc9 rm temp.txt
2
有两种恢复方式:
- 用
git stash apply
恢复,但是恢复后,stash 内容并不删除,你需要用git stash drop
来删除;类似读取栈的内容,但不弹出 - 用
git stash pop
,恢复的同时把 stash 内容也删了。
我们使用第二种方式,可以看到 Git 会将当前仓库状态显示出来:
$ git stash pop
On branch bug02
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: 3-branch/branch.txt
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (a81ac38b932b00c0f934f613f823c33c7e37b10d)
2
3
4
5
6
7
8
9
并且文件内容也恢复了:
$ cat 3-branch/branch.txt
Creating a new branch is quick and simple
test no fast forward
fuk
2
3
4
你可以多次 stash,恢复的时候,先用 git stash list
查看,然后恢复指定的 stash,用命令:
$ git stash apply stash@{0}
再用 git stash list
查看,就看不到任何 stash 内容了:
$ git stash list
# 更多 stash 用法
我们在存储现场的时候,还可以加一些注释,方便我们回忆:git stash save "test"
$ git stash save "temp"
Saved working directory and index state On bug02: temp
peterjxl@peter MINGW64 /d/Projects/LearnGit (bug02)
$ git stash list
stash@{0}: On bug02: temp
2
3
4
5
6
更多 stash 的用法,就不一一演示了:
git stash clear
:清除堆栈中的所有内容
git stash show
:查看堆栈中最新保存的 stash 和当前目录的差异。
git stash show stash@{1}
:查看指定的 stash 和当前目录差异。
git stash branch
:从最新的 stash 创建分支。
# 复制一个提交
现在我们假设这样一个场景:
- 我们从 master 分支上,创建了 feature 分支开发一个新功能
- 此时突然来了个比较紧急的 bug,是 master 分支上的
- 我们从 master 分支上创建一个分支 bug,并修复了该 bug
- 继续回到 feature 分支开发
目前有这样一个问题,我们的 feature 分支也是从 master 分支上拉出来的,所以那个 bug 在当前分支也是存在的!那要怎么修复?一个方法是将 bug 再一次在 feature 分支上修复一次,但这样又花了不少时间做重复的事情。
git 专门提供了一个 cherry-pick
命令,让我们能复制一个特定的提交到当前分支。我们来演示下:
先删除其他分支,并确保当前工作区是干净的
$ git branch
* master
2
创建 feature 分支和 bug 分支:
$ git branch feature
$ git branch bug
$ git branch
bug
feature
* master
2
3
4
5
6
7
8
切换到 bug 分支上,并修改 branch.txt,添加一个词组 cherry-pick:
$ git switch bug
$ vim 3-branch/branch.txt
$ cat 3-branch/branch.txt
Creating a new branch is quick and simple
test no fast forward
test cherry-pick
$ git add 3-branch/branch.txt
$ git commit -m "fix bug"
[bug 1794212] fix bug
1 file changed, 1 insertion(+), 1 deletion(-)
2
3
4
5
6
7
8
9
10
11
12
13
14
这里记录下 commit id 是 1794212,后续会用到。
然后切换到 master 分支,合并 bug 分支:
$ git switch master
$ git merge --no-ff -m "merged bug fix" bug
Merge made by the 'recursive' strategy.
3-branch/branch.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
2
3
4
5
然后切换到 feature 分支,并复制提交:
$ git cherry-pick 1794212
[feature 88085eb] fix bug
Date: Sat Jan 14 20:06:01 2023 +0800
1 file changed, 1 insertion(+), 1 deletion(-)
$ cat 3-branch/branch.txt
Creating a new branch is quick and simple
test no fast forward
test cherry-pick
2
3
4
5
6
7
8
9
Git 自动给 feature 分支做了一次提交,注意这次提交的 commit 是 88085eb
,它并不同于 master 的 1794212
,因为这两个 commit 只是改动相同,但确实是两个不同的 commit:
$ git log --oneline
88085eb (HEAD -> feature) fix bug
982423c add test to branch.txt
a2f5dc9 rm temp.txt
b194598 add temp.txt
2
3
4
5
用 git cherry-pick
,我们就不需要在 feature 分支上手动再把修 bug 的过程重复一遍。