Skip to content

Git stash - 暂存操作 #126

@tcatche

Description

@tcatche

本文博客地址:Git stash - 暂存操作.

当正在进行某项开发任务过程中,突然有另一件紧急的事情需要处理,比如有线上问题,这个时候,当前代码并没有开发完成不想提交, git stash 命令就是一个解决此问题的方法。

stash 命令可以把当前未提交的内容给暂存起来,还原到上次提交的状态,然后可以在任意合适的时刻,以及任意分支,把这些变动给还原回来。

本文看一下 git stash 相关的命令。注意,本文中示例 $ 开头的表示执行的命令,其他内容为命令的输出。

git stash

git stash [push [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
	     [-u|--include-untracked] [-a|--all] [-m|--message <message>]
	     [--pathspec-from-file=<file> [--pathspec-file-nul]]
	     [--] [<pathspec>…​]]

首先进入一个 git 仓库,使用 git status 查看一下状态:

$ cd test
$ git status

# 输出
  On branch test
  nothing to commit, working tree clean

可以看到此时工作区是干净的,没有任何变更,尝试修改一个文件:

$ echo 'stashed change' > README.md
$ git status

  On branch test
  Untracked files:
    (use "git add <file>..." to include in what will be committed)
          modified:   README.md

  nothing added to commit but untracked files present (use "git add" to track)

这个时候,有新的工作需要处理,执行 git stash 来暂存文件:

$ git stash

  Saved working directory and index state WIP on test: 3ef7d58 release 1.0

  $ git status
  On branch test
  nothing to commit, working tree clean

可以看到此时工作区已经回到了编辑前的干净状态,这个时候就可以进行其他的修改了。

使用 -m 命令可以在stash 时设置message:

$ git stash -m "debug code"

$ git stash list

  stash@{0}: On test: debug code
  stash@{1}: WIP on test: 3ef7d58 release 1.0
  stash@{2}: WIP on test: 3ef7d58 release 1.0

默认情况下,stash 只会保存已修改和暂存的 已追踪文件,也就是说未被追踪过的文件是无法保存的,下面尝试新建一个文件来保存:

$ touch newfile

$ git stash

  No local changes to save

$ git status

  On branch test
  Untracked files:
    (use "git add <file>..." to include in what will be committed)
          newfile

nothing added to commit but untracked files present (use "git add" to track)

可以看到新建的文件无法被存储,这个时候可以加上 --include-untracked-u 参数,可以看到,此时新增加的文件也被 stash 暂存了:

$ git stash -u

  Saved working directory and index state WIP on test: 3ef7d58 release 1.0

$ git status

  On branch test
  nothing to commit, working tree clean

git stash list

git stash list [<log-options>]

git stash list 用于查看当前的 stash 都存储了哪些内容:

$ git stash list

  stash@{0}: WIP on test: 3ef7d58 release 1.0
  stash@{1}: WIP on test: 3ef7d58 release 1.0
  stash@{2}: WIP on test: 3ef7d58 release 1.0

每个保存的 stash 都有个 name,如上命令的输出看到,格式为stash@{<name>},stash 使用了栈的存储结构,所以数字越小的是越近保存的,如 stash@{0} 是最新保存的,stash@{2} 是最早保存的。

从上面的语法可以看出 stash list 命令还支持 git log 命令的参数,比如使用 --pretty=oneline 命令查看 stash 的详细改动:

$ git stash list --pretty=oneline

  e2a114ca7692a1415b6d97e71dee8935af251a41 (refs/stash) refs/stash@{0}: WIP on test: 3ef7d58 release 1.0
  6446c1dffa700c1b603396c19a372ce1cdd63956 refs/stash@{1}: WIP on test: 3ef7d58 release 1.0
  e32b6ec77994ada19051586af37b0bc595bd9605 refs/stash@{2}: WIP on test: 3ef7d58 release 1.0

git stash show

git stash show [diff-options] [stash]

git stash show 用于查看 stash 存储的改动,默认展示最近一次的改动:

$ git stash show

  README.md | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

如果要看其它的存储,可以加上 stash name

$ git stash list

  stash@{0}: WIP on test: 3ef7d58 release 1.0

$ git stash show stash@{0}

  README.md | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

从上面的语法可以看出 stash show 命令还支持 git diff 命令的参数,比如使用 -p 命令,可以查看 stash 的详细改动:

$ git stash show -p

  diff --git a/README.md b/README.md
  index ec3514a..79105b0 100644
  --- a/README.md
  +++ b/README.md
  @@ -1 +1 @@
  -'test'
  +'stashed change version 3'

git stash drop

git stash drop [-q|--quiet] [stash]

git stash drop 用于删除 stash 中的某个存储:

$ git stash list

  stash@{0}: WIP on test: 3ef7d58 release 1.0
  stash@{1}: WIP on test: 3ef7d58 release 1.0
  stash@{2}: WIP on test: 3ef7d58 release 1.0

$ git stash drop stash@{2}
  Dropped stash@{2} (e32b6ec77994ada19051586af37b0bc595bd9605)

$ git stash list

  stash@{0}: WIP on test: 3ef7d58 release 1.0
  stash@{1}: WIP on test: 3ef7d58 release 1.0

git stash apply

git stash apply [--index] [-q|--quiet] [stash]

git stash applygit stash 的反操作,将 stash 保存的状态还原到工作区,也就是还原指定的 stash 的内容:

$ echo 'stashed and restore' > README.md

$ git status

  On branch test
  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:   README.md

  no changes added to commit (use "git add" and/or "git commit -a")

$ git stash

  Saved working directory and index state WIP on test: 3ef7d58 release 1.0

$ git status

  On branch test
  nothing to commit, working tree clean

$ git stash apply

  On branch test
  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:   README.md

  no changes added to commit (use "git add" and/or "git commit -a")

从上面的操作可以看出,执行了 git stash apply 后,工作取得状态又还原回 git stash 之前的状态了。

git stash pop

git stash pop [--index] [-q|--quiet] [stash]

git stash popgit stash apply 的作用完全一样,不同点在于 git stash apply 不会stash 中删除还原的 stash,而 git stash pop 从 stash 中删除:

$ git stash list

  stash@{0}: WIP on test: 3ef7d58 release 1.0
  stash@{1}: WIP on test: 3ef7d58 release 1.0
  stash@{2}: WIP on test: 3ef7d58 release 1.0

$ git stash apply
$ git stash list

  stash@{0}: WIP on test: 3ef7d58 release 1.0
  stash@{1}: WIP on test: 3ef7d58 release 1.0
  stash@{2}: WIP on test: 3ef7d58 release 1.0

$ git stash pop
$ git stash list
  stash@{0}: WIP on test: 3ef7d58 release 1.0
  stash@{1}: WIP on test: 3ef7d58 release 1.0

从上面的例子可以看出 git stash apply 执行后 stash list 没有变化,而 git stash pop 执行后 stash list 里没有了此内容。

git stash clear

git stash clear 用于清除所有 stash 里存储的内容:

$ git stash list
  stash@{0}: WIP on test: 3ef7d58 release 1.0

$ git stash clear
$ git stash list
//输出空

可以看到,此时的 stash 已经被清空了。

git stash branch

git stash branch <branchname> [<stash>]

git stash branch 命令会以指定的分支名创建一个新分支,然后从 stash 中 检出存储的内容,然后从 stash 中丢弃保存的内容:

$ git stash list

  stash@{0}: WIP on test: 3ef7d58 release 1.0
  stash@{1}: WIP on test: 3ef7d58 release 1.0
  stash@{2}: WIP on test: 3ef7d58 release 1.0

$ git stash branch test-stash stash@{1}

  Switched to a new branch 'test-stash'
  On branch test-stash
  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:   README.md

  no changes added to commit (use "git add" and/or "git commit -a")
  Dropped stash@{1} (9a6040c186a91874c6949f5ec29de61b9bcc1014)

$ git stash list

  stash@{0}: WIP on test: 3ef7d58 release 1.0
  stash@{1}: WIP on test: 3ef7d58 release 1.0
  stash@{2}: WIP on test: 3ef7d58 release 1.0

git stash create/store

两个命令不常用,就不总结了,详细可以查看 git 的文档。

参考

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions