找回Git中丟失的Commit

 

在使用Git的過程當中,有時候會由於一些誤操做,好比reset、rebase、merge等。特別是在Commit以後又執行了git reset --hard HEAD強制回滾本地記錄以及文件到服務器版本,致使本地作的修改所有恢復到Git當前分支的服務器版本,同時本身的Commmit記錄也消失了。碰到這種狀況,不要慌,咱們在Git上作的任何操做都只是在原來以前的操做上作修改,而且會被記錄下來保存,也就是說不管你作了什麼,對於Git來講均可以進行回滾操做。git

找回Commit

經過如下例子來了解下具體怎麼回滾: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進行回滾,若是在b7057a998abc5a之間還有其餘的Commit操做,則會忽略中間的這些Commit作的修改,因此應用這個命令有可能會文件的衝突string

git reset的具體用法

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 的狀況下才永久刪除。

相關文章
相關標籤/搜索