在使用Git的过程当中,有时候会由于一些误操做,好比reset、rebase、merge等。特别是在Commit以后又执行了git reset --hard HEAD
强制回滚本地记录以及文件到服务器版本,致使本地作的修改所有恢复到Git当前分支的服务器版本,同时本身的Commmit记录也消失了。碰到这种状况,不要慌,咱们在Git上作的任何操做都只是在原来以前的操做上作修改,而且会被记录下来保存,也就是说不管你作了什么,对于Git来讲均可以进行回滚操做。git
经过如下例子来了解下具体怎么回滚:sql
$ git init $ touch foo.txt $ echo 'test data' >> foo.txt $ git add foo.txt $ git commit -m "initial commit" $ echo 'new data' >> foo.txt $ git commit -a -m "more stuff added to foo"
你如今看git的历史记录,你能够看到两次提交:ruby
$ git log
* 98abc5a (HEAD, master) more stuff added to foo * b7057a9 initial commit
如今让咱们来重置回第一次提交的状态:服务器
$ git reset --hard b7057a9 $ git log * b7057a9 (HEAD, master) initial commit
这看起来咱们是丢掉了咱们第二次的提交,本地的修改也消失了,没有办法找回来了。可是 reflog 就是用来解决这个问题的。简单的说,它会记录全部HEAD的历史,也就是说当你作 reset,checkout等操做的时候,这些操做会被记录在reflog中。markdown
$ git reflog
b7057a9 HEAD@{0}: reset: moving to b7057a9 98abc5a HEAD@{1}: commit: more stuff added to foo b7057a9 HEAD@{2}: commit (initial): initial commit
因此,咱们要找回咱们第二commit,只须要作以下操做:spa
$ git reset --hard 98abc5a
再来看一下 git 记录:code
$ git log
* 98abc5a (HEAD, master) more stuff added to foo * b7057a9 initial commit
同时本地对foo.txt作的修改也回复回来了。索引
PS:这里在提一下另外一个找回Commit的操做
git cherry-pick 98abc5a
,这个操做与上面的reset操做区别在于后者只是单纯的提取98abc5a这个Commit进行回滚,若是在b7057a9和98abc5a之间还有其余的Commit操做,则会忽略中间的这些Commit作的修改,因此应用这个命令有可能会文件的冲突string
git reset [--hard|soft|mixed|merge|keep] [<commit>或HEAD]
做用:将当前分支reset到指定的<commit>或者HEAD(默认为最新的一次提交,即重设到最新一次提交以前的版本)it
备注:
- index,执行git add的操做,会对文件建立索引,全部被跟踪的文件索引会放入index,表示文件被修改待提交
- working tree,当前工做区,被修改但未被add的文件,存储在工做区
- ORIG_HEAD,用于指向前一个操做状态,每次的commit或者pull或者reset,git 都会把老的HEAD拷贝到.git/ORIG_HEAD,经过对ORIG_HEAD的引用能够指向前一次的操做状态
一、hard(慎用)
重设index和working tree,全部改变都会被丢弃,包括文件的修改、新增、删除等操做,并把HEAD指向<commit>,
所以经过git log查看版本提交记录,被reset的版本记录会被丢弃,但能够经过git reflog查看
二、soft
不重设index和working tree,仅仅将HEAD指向<commit>,表示已经commit的文件会取消commit,
经过git status查看,文件会处于待commit状态“Changes to be committed”
三、mixed(默认)
重设index,但不重设working tree,表示已经被add的文件,被取消add,
经过git status查看,文件会处于待添加索引状态 “Changes not staged for commit”
四、merge
重设index,重设working tree中发生变化的文件,可是保留index和working tree不一致的文件
五、keep
重设index,重设working tree中发生变化的文件
咱们前面说到在Git上作的全部操做都被保存到记录里,通常是从你本地Git库执行clone开始的全部操做都保存了下来,因此不用担忧好久以前的一些Commit log找不到,你或许指望去为已删除的提交设置一个更长的保存周期。例如:$ git config gc.pruneexpire "30 days"
意思是一个被删除的提交会在删除30天后,且运行 git gc 之后,被永久丢弃。
你或许还想关掉 git gc 的自动运行:$ git config gc.auto 0
在这种状况下提交将只在你手工运行 git gc 的状况下才永久删除。