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 -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
文件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