揭秘 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"

‍

接下来,我们切换并修改 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

‍

接下来我们切换,果然,报错了:

$ 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

‍

Git 告诉我们可以提交后再切换;但是我们目前仅仅开发到一半,不想提交,怎么办?

‍

Git stash 演示

Git 提供了 stash 功能,可以把当前工作现场“储藏”起来,等以后恢复现场后继续工作:

$ git stash
Saved working directory and index state WIP on bug02: a2f5dc9 rm temp.txt

‍

‍

‍

现在,用 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

‍

‍

等后续修复完 bug 后,如何恢复现场呢?首先,我们的工作现场是存储在一个栈里的,我们可以查看当前有哪些工作现场:

$ git stash list
stash@{0}: WIP on bug02: a2f5dc9 rm temp.txt

‍

有两种恢复方式:

  1. 用 git stash apply ​恢复,但是恢复后,stash 内容并不删除,你需要用 git stash drop ​来删除;类似读取栈的内容,但不弹出
  2. 用 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)

‍

并且文件内容也恢复了:

$ cat 3-branch/branch.txt
Creating a new branch is quick and simple
test no fast forward
fuk

‍

‍

你可以多次 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

‍

更多 stash 的用法,就不一一演示了:

git stash clear​:清除堆栈中的所有内容

git stash show​:查看堆栈中最新保存的 stash 和当前目录的差异。

git stash show stash@{1}​:查看指定的 stash 和当前目录差异。

git stash branch​:从最新的 stash 创建分支。

‍

‍

复制一个提交

现在我们假设这样一个场景:

  1. 我们从 master 分支上,创建了 feature 分支开发一个新功能
  2. 此时突然来了个比较紧急的 bug,是 master 分支上的
  3. 我们从 master 分支上创建一个分支 bug,并修复了该 bug
  4. 继续回到 feature 分支开发

‍

目前有这样一个问题,我们的 feature 分支也是从 master 分支上拉出来的,所以那个 bug 在当前分支也是存在的!那要怎么修复?一个方法是将 bug 再一次在 feature 分支上修复一次,但这样又花了不少时间做重复的事情。

git 专门提供了一个 cherry-pick ​命令,让我们能复制一个特定的提交到当前分支。我们来演示下:

‍

先删除其他分支,并确保当前工作区是干净的

$ git branch
* master

‍

创建 feature 分支和 bug 分支:

$ git branch feature

$ git branch bug

$ git branch
  bug
  feature
* master

‍

切换到 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(-)

这里记录下 commit id 是 1794212,后续会用到。

‍

‍

然后切换到 master 分支,合并 bug 分支:

$ git switch master
$ git merge --no-ff -m &quot;merged bug fix&quot; bug
Merge made by the 'recursive' strategy.
 3-branch/branch.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

‍

‍

然后切换到 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

‍

‍

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

用 git cherry-pick​​,我们就不需要在 feature 分支上手动再把修 bug 的过程重复一遍。

‍

‍

‍

(完)

posted @ 2024-09-26 11:05  peterjxl  阅读(188)  评论(0)    收藏  举报