git stash

本文介绍 Git stash 命令的详细用法,包括如何保存、列出、恢复和删除工作进度。并通过实例演示如何利用 Git stash 管理临时更改。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

git stash list 查看保存的进度

git stash pop 从最近保存的进度进行恢复

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   a/b/c/hello.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   welcome.txt

1)以当前暂存区的状态进行提交,即只提交 a/b/c/hello.txt ,不提交 welcome.txt

$ git commit -m "add new file:a/b/c/hello.txt,but leave welcome.txt alone"
[master 89a786a] add new file:a/b/c/hello.txt,but leave welcome.txt alone
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a/b/c/hello.txt

查看提交后的状态

$ git status -s
 M welcome.txt



2)反悔了,回到之前的状态。用重置命令放弃最新的提交

$ git reset --soft HEAD^


工作区和暂存区的状态都维持在原来的状态

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   a/b/c/hello.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   welcome.txt


3)想将welcome.txt提交

$ git add welcome.txt
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   a/b/c/hello.txt
        modified:   welcome.txt


4)想将a/b/c.txt撤出暂存区,也就是重置命令

$ git reset HEAD a/b/c
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   welcome.txt

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

        a/


5)想将剩下的文件(welcome.txt)从暂存区撤出,就是说不想提交任何东西了。

还是重置命令,甚至可以不使用任何参数。

$ git reset
Unstaged changes after reset:
M       welcome.txt


6)想将本地工作区所有的修改清楚。即清除welcome.txt的改动,删除添加的目录a以及下面的子目录和文件

清楚welcome.txt的改动用检出命令(实际对于此例执行 git checkout . 也可以)

$ git checkout -- welcome.txt

工作区还显示一个多余的目录a

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

        a/

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


删除本地多余的目录和文件,使用git clean 命令。

先来测试运行以便看看哪些文件和目录会被删除,以免造成误删。

$ git clean -nd
Would remove a/


真正开始强制删除多余的目录和文件

$ git clean -fd
Removing a/


整个世界都清净了。

$ git status
On branch master
nothing to commit, working directory clean

使用git stash

git  stash

保存当前的工作进度。会分别对暂存区和工作区的状态进行保存。


git stash list

显示进度列表。此命令说明 git stash可以多次保存工作进度,并将恢复的时候进行选择。


git  stash  pop  [--index]   [<stash>]

如果不使用任何参数,会恢复最新保存的工作进度,并将恢复的工作进度从存储的工作进度列表中清除。

如果提供<stash>参数(来自于git stash list显示的列表),则从该<stash>中恢复。恢复完毕也将从进度列表中删除<stash>

选项--index除了恢复工作区的文件外,还尝试恢复暂存区。


git  stash  [save  [--patch]  [-k | --[no-]keep-index]  [-q|--quiet]  [<message>]  ]

这条命令是git  stash的完整版。即如果需要在保存工作进度的时候使用指定的说明,必须如下格式: git  stash save "message"

--patch会显示工作区和HEAD的差异,通过对差异文件的编辑决定再进度中最终要保存的工作区的内容,通过编辑差异文件可以在进度中排出无关内容。

-k  或者 --keep-index,在保存进度后不会将暂存区重置。默认会将暂存区和工作区强制重置。


git  stash apply  [--index]  [<stash>]

除了不删除恢复的进度之外,其余和git  stash  pop一样


git  stash  drop  [<stash>]

删除一个存储的进度。默认删除最新的进度。


git  stash  clear

删除所有存储的进度


git  stash  branch <branchname>  <stash>

基于进度创建分支


探秘 git stash

执行git  stash命令时,实际调用了脚本文件 git-stash

$ git --exec-path
D:\Git\mingw64/libexec/git-core
$ ls D:/Git/mingw64/libexec/git-core
edit.dll*
git.exe*
git-add.exe*
git-add--interactive*
git-am.exe*
git-annotate.exe*
git-apply.exe*
git-archimport*
git-archive.exe*
git-bisect*
git-bisect--helper.exe*
git-blame.exe*
git-branch.exe*
git-bundle.exe*
git-cat-file.exe*
git-check-attr.exe*
git-check-ignore.exe*
git-check-mailmap.exe*
git-checkout.exe*
......
git-<cmd>作为软件本身的名称,而其命令行为git  <cmd>

$ file D:/Git/mingw64/libexec/git-core/git-stash
D:/Git/mingw64/libexec/git-core/git-stash: POSIX shell script, ASCII text executable


示例:

当前的进度保存列表是空的

$ git stash list


下面更改文件

$ echo Bye-Bye.>>welcome.txt
$ echo hello.>hack-1.txt
$ git add hack-1.txt

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   hack-1.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   welcome.txt
可见暂存区中已经添加了hack1-text,修改过的welcome.txt并未添加到暂存区。


保存下工作进度

$ git stash save "hack-1: hacked welcome.txt, newfile hack-1.txt"
Saved working directory and index state On master: hack-1: hacked welcome.txt, newfile hack-1.txt
HEAD is now at 19d2c13 welcome txt


工作区恢复了修改之前的原貌(实际上用了 git  reset --hard  HEAD)

文件welcome.txt的修改不见了,文件hack-1.txt整个都不见了

$ git status
On branch master
nothing to commit, working directory clean

$ ls
abc.txt  detached-commit.txt  new-commit.txt  welcome.txt

$ cat welcome.txt


再做个修改,并尝试保存进度

$ echo flx. >hack-2.txt

$ git stash
No local changes to save
可见本地没有被版本控制系统跟踪的文件并不能保存进度。

因为本地新文件需要先执行添加操作,然后再执行 git stash命令

$ git add hack-2.txt

$ git stash
Saved working directory and index state WIP on master: 19d2c13 welcome txt
HEAD is now at 19d2c13 welcome txt


该工作区再次恢复原状

$ git stash list
stash@{0}: WIP on master: 19d2c13 welcome txt
stash@{1}: On master: hack-1: hacked welcome.txt, newfile hack-1.txt
1.在使用git stash保存进度时,提供说明 则更容易通过进度列表找到保存的进度

2.每个进度的标识都是stash@{<n>}格式

实际上,git stash就是用引用和引用变更日志(reflog)来实现的。

$ ls -l .git/refs/stash .git/logs/refs/stash
-rw-r--r-- 1 nanayin 1049089 355 一月  6 13:59 .git/logs/refs/stash
-rw-r--r-- 1 nanayin 1049089  41 一月  6 13:59 .git/refs/stash

$ git reflog show refs/stash
97e6838 refs/stash@{0}: WIP on master: 19d2c13 welcome txt
e86bbeb refs/stash@{1}: On master: hack-1: hacked welcome.txt, newfile hack-1.txt
git  stash 保存进度,实际上会将进度保存在引用 refs/stash 所指向的提交中。

多次的进度保存,实际上上相当于引用refs/stash一次又一次的变化,而refs/stash 引用的变化由 reflog(即.git/logs/refs/stash)所记录下来


$ git log --graph --pretty=raw refs/stash -2
*   commit 97e6838201fe78c86b66135a881e86a12f7ba6a1
|\  tree 76a5346966b7b913c8851cca4b2dd1141c696703
| | parent 19d2c13bd1eaa3e1c8319142fd6daaf6d0f29c52
| | parent 6b043db393e94e77b65598386576ffa619e0b531
| | author yinnana <nanayin@creditease.cn> 1483682381 +0800
| | committer yinnana <nanayin@creditease.cn> 1483682381 +0800
| |
| |     WIP on master: 19d2c13 welcome txt
| |
| * commit 6b043db393e94e77b65598386576ffa619e0b531
|/  tree 76a5346966b7b913c8851cca4b2dd1141c696703
|   parent 19d2c13bd1eaa3e1c8319142fd6daaf6d0f29c52
|   author yinnana <nanayin@creditease.cn> 1483682374 +0800
|   committer yinnana <nanayin@creditease.cn> 1483682374 +0800
|
|       index on master: 19d2c13 welcome txt

WIP(work in progess) 代表工作区的进度

index on master 代表着暂存区的进度

$ git log --graph --pretty=raw stash@{1} -3
*   commit e86bbeb80bc3058dd23b6ef4649fda66b85b5763
|\  tree 3d9752ad0a97ea4cff50a2ae6a71d1c44b50ac30
| | parent 19d2c13bd1eaa3e1c8319142fd6daaf6d0f29c52
| | parent dcf1372f21ab563a69dfdf326a3b6622f4e939c7
| | author yinnana <nanayin@creditease.cn> 1483682045 +0800
| | committer yinnana <nanayin@creditease.cn> 1483682045 +0800
| |
| |     On master: hack-1: hacked welcome.txt, newfile hack-1.txt
| |
| * commit dcf1372f21ab563a69dfdf326a3b6622f4e939c7
|/  tree db9fd17b7cdaa1a8aa08a06431ae88b5ea9d7269
|   parent 19d2c13bd1eaa3e1c8319142fd6daaf6d0f29c52
|   author yinnana <nanayin@creditease.cn> 1483682042 +0800
|   committer yinnana <nanayin@creditease.cn> 1483682042 +0800
|
|       index on master: 19d2c13 welcome txt
|
* commit 19d2c13bd1eaa3e1c8319142fd6daaf6d0f29c52
| tree 7dbbceab4b80697b093d08ef8b52a69dd4c35c37
| parent 45ad43e40b1c76bc08f36d1d31ab08562b54652d
| author yinnana <nanayin@creditease.cn> 1483667600 +0800
| committer yinnana <nanayin@creditease.cn> 1483667600 +0800
|
|     welcome txt
“原基线” 代表保存时版本库的状态,即提交19d2c13

“原暂存区”代表进度保存时暂存区的状态,即提交dcf137

“原工作区”代表进度保存时工作区的状态,即提交e86bbe

原基线和原暂存区的差异比较

$ git diff stash@{1}^2^ stash@{1}^2
diff --git a/hack-1.txt b/hack-1.txt
new file mode 100644
index 0000000..25735f5
--- /dev/null
+++ b/hack-1.txt
@@ -0,0 +1 @@
+hello.

原暂存区和原工作区的差异比较

nanayin@201605050385- MINGW64 /f/gitdemo (master)
$ git diff stash@{1}^2 stash@{1}
diff --git a/welcome.txt b/welcome.txt
index e69de29..b22d129 100644
--- a/welcome.txt
+++ b/welcome.txt
@@ -0,0 +1 @@
+Bye-Bye.

原基线和原工作区的差异比较

$ git diff stash@{1}^1 stash@{1}
diff --git a/hack-1.txt b/hack-1.txt
new file mode 100644
index 0000000..25735f5
--- /dev/null
+++ b/hack-1.txt
@@ -0,0 +1 @@
+hello.
diff --git a/welcome.txt b/welcome.txt
index e69de29..b22d129 100644
--- a/welcome.txt
+++ b/welcome.txt
@@ -0,0 +1 @@
+Bye-Bye.


用stash@{1}来恢复进度

$ git stash apply stash@{1}
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   hack-1.txt

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   welcome.txt


显示进度列表,然后删除进度列表

$ git stash list
stash@{0}: WIP on master: 19d2c13 welcome txt
stash@{1}: On master: hack-1: hacked welcome.txt, newfile hack-1.txt
$ git stash clear


删除进度列表之后,会发现stash相关的引用和reflog都不见了
$ ls -l .git/refs/stash .git/logs/refs/stash
ls: cannot access '.git/refs/stash': No such file or directory
ls: cannot access '.git/logs/refs/stash': No such file or directory

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值