9.1 恢复保存的进度git
查看第五章保存的进度:app
$ git stash list stash@{0}: WIP on master: 326f237 which version checked in?
恢复进度:测试
$ git stash pop 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 Dropped refs/stash@{0} (eca70a6e0ecccaddf3641263eb341c4541779ae9)
查看工做区状态,进度已经找回了:ui
$ 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
对找回进度的工做区作如下处理:3d
(1)对当前的暂存区进行提交:日志
$ git commit -m "add new file: a/b/c/hello.txt, but leave welcome.txt alone" [master 9e5eaa3] add new file: a/b/c/hello.txt, but leave welcome.txt alone 1 file changed, 2 insertions(+) create mode 100644 a/b/c/hello.txt $ git status -s M welcome.txt
(2)撤销以前的提交,工做区和暂存区的状态也都维持在原来的状态:code
$ git reset --soft HEAD^ $ git log -1 --pretty=oneline 0463e7ae492200b77525642fb77d8f8fa03913c1 Merge commit '64cc27237' $ git status -s A a/b/c/hello.txt M welcome.txt
(3)将welcome.txt的修改提交到暂存区:开发
$ git add welcome.txt $ git status -s A a/b/c/hello.txt M welcome.txt
(4)将a/b/c/hello.txt撤出暂存区:rem
$ git reset HEAD a/b/c $ git status -s M welcome.txt ?? a/
(5)将全部内容存暂存区中撤出:it
$ git reset Unstaged changes after reset: M welcome.txt
(6)清除welcome.txt个改动:
$ git checkout -- welcome.txt $ 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)
(7)删除目录a,删除本地多余的目录和文件,可使用git clean命令。先运行测试命令查看哪些文件和目录会被删除以避免形成误删:
$ git clean -nd Would remove a/
使用-f参数强制删除文件和目录:
$ git clean -fd Removing a/
9.2 git stash命令
一、git stash
保存当前的工做进度,会分别对暂存区和工做区的状态进行保存;
二、git stash list
显示进度列表。
三、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> <strach>
基于进度建立分支。
9.3 git stash深刻
在执行git stash命令时,Git实际调用了一个脚本文件实现相关的功能,这个脚本的文件名是git-stash。使用下面的命令查看git-stash的安装位置:
$ git --exec-path C:\Program Files\Git\mingw64/libexec/git-core
这个目录下包含了Git命令脚本,最初这些命令都是用Shell或Perl脚本语言开发的,在Git发展中一些对运行效率要求高的命令用C语言改写。在Git 1.7.4版本以前git-stash仍是使用Shell脚本开发的。
查看当前的进度保存列表是空的:
$ git stash list
在工做区作一些改动:
$ echo Bye-Bye. >> welcome.txt $ echo hello. > hack-1.txt $ git add hack-1.txt $ git status -s A hack-1.txt M welcome.txt
执行git stash保存工做进度:
$ 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 0463e7a Merge commit '64cc27237' $ git status -s $ ls detached-commit.txt new-commit.txt welcome.txt
保存完成后工做区恢复了修改前的原貌(实际上用了git reset --hard HEAD命令),文件welcome.txt的修改不见了,文件hack-1.txt整个不见了。
再作一个修改,并尝试保存进度:
$ echo fix. > 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: 0463e7a Merge commit '64cc27237' HEAD is now at 0463e7a Merge commit '64cc27237'
工做区又恢复了原状。查看进度保存状况:
$ git stash list stash@{0}: WIP on master: 0463e7a Merge commit '64cc27237' stash@{1}: On master: hack-1: hacked welcome.txt, newfile hack-1.txt
每一个进度的标识都是stash@[<n>]格式,与reflog的格式很类似。实际上,git stash就是用前面介绍的引用和引用变动日志(reflog)来实现的。有关进度的文件:
$ ls -l .git/refs/stash .git/logs/refs/stash -rw-r--r-- 1 x250 197121 360 七月 18 21:45 .git/logs/refs/stash -rw-r--r-- 1 x250 197121 41 七月 18 21:45 .git/refs/stash
使用git reflog能够查看进度状况:
$ git reflog show refs/stash 04cae38 refs/stash@{0}: WIP on master: 0463e7a Merge commit '64cc27237' 43f13c7 refs/stash@{1}: On master: hack-1: hacked welcome.txt, newfile hack-1.txt
对照git reflog的结果和前面git stash list的结果,能够确定git stash保存进度,实际上会将进度保存在引用refs/stash所指向的提交中。屡次的进度保存,实际上至关于引用refs/stash一次又一次的变化(refs/stash只记录一次进度的ID),而refs/stash引用的变化由reflog(.git/logs/refs/stash)所记录下来。
如何在引用refs/stash中同时保存暂存区的进度和工做区中的进度?
查看引用refs/stash的提交历史:
$ git log --graph --pretty=raw refs/stash -2 * commit 04cae38d64c6c6cc7e7421c08349c8a3b75ae7dd |\ tree 7032578d4dd41c43b4e62c8806e4b7ad3f9a54e6 | | parent 0463e7ae492200b77525642fb77d8f8fa03913c1 | | parent de586678f3ac0d423a469b6e26968741b6e46344 | | author jiangzhi <ivanjz93@163.com> 1468849531 +0800 | | committer jiangzhi <ivanjz93@163.com> 1468849531 +0800 | | | | WIP on master: 0463e7a Merge commit '64cc27237' | | | * commit de586678f3ac0d423a469b6e26968741b6e46344 |/ tree 7032578d4dd41c43b4e62c8806e4b7ad3f9a54e6 | parent 0463e7ae492200b77525642fb77d8f8fa03913c1 | author jiangzhi <ivanjz93@163.com> 1468849531 +0800 | committer jiangzhi <ivanjz93@163.com> 1468849531 +0800 | | index on master: 0463e7a Merge commit '64cc27237'
从提交历史中能够看到进度保存的最新提交时一个合并提交。最新的提交说明中有WIP字样(Work In Proress),表明了工做区进度。最新提交的第二个父提交有index on master标记,说明这个提交表明暂存区的进度。
但提交历史中的两个提交都指向了同一个树,这是由于最后一次作进度保存时工做区相对暂存区没有改变。
第一次进度的保存工做区、暂存区和版本库的各不相同。第一次进度保存可使用reflog中的语法,即用refs/stash@{1}来访问,也能够简写成stash@{1}。
$ git log --graph --pretty=raw stash@{1} -3 * commit 43f13c7c4b13f480032c64b9375f97d16931ba35 |\ tree 3cd11ce48979a5f97e28304b1237cfb6d4a8cf7e | | parent 0463e7ae492200b77525642fb77d8f8fa03913c1 | | parent 7b3bef783f4d0900b185c4ba4b33646a1090660a | | author jiangzhi <ivanjz93@163.com> 1468831199 +0800 | | committer jiangzhi <ivanjz93@163.com> 1468831199 +0800 | | | | On master: hack-1: hacked welcome.txt, newfile hack-1.txt | | | * commit 7b3bef783f4d0900b185c4ba4b33646a1090660a |/ tree 9c34579bf4f5504b9b0376097814d5c1cdb8bbdc | parent 0463e7ae492200b77525642fb77d8f8fa03913c1 | author jiangzhi <ivanjz93@163.com> 1468831198 +0800 | committer jiangzhi <ivanjz93@163.com> 1468831198 +0800 | | index on master: 0463e7a Merge commit '64cc27237' | * commit 0463e7ae492200b77525642fb77d8f8fa03913c1 |\ tree ad4eca82e587a477b91a4f7bbfef97c7921e52cc | | parent 1ce417a21fcd936e333db5f56a79a04ae2785a08 | | parent 64cc27237267d702e31e34fe0b75db97f5171001 | | author jiangzhi <ivanjz93@163.com> 1468822001 +0800 | | committer jiangzhi <ivanjz93@163.com> 1468822001 +0800 | | Merge commit '64cc27237'
第一个表明保存时工做区的状态(原工做区),第二个表明保存时暂存区的状态(原暂存区),第三个表明保存时版本库的状态(原基线)。
用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: 0463e7a Merge commit '64cc27237' 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