分享後端開發和雲計算必備相關技術,道盡程序員小熊與老闆的愛恨情仇.linux
同名公衆號:編程三分鐘 回覆【 資源 】能夠得到程序員必備技能圖譜、數百本熱門編程電子書籍。git
「 新來的實習生把本身作了一個月的功能給覆蓋了,向我求救,要不要幫他?——編程三分鐘」程序員
新來的實習生【悲郭】由於不太熟悉git的使用,老是把本身的代碼給弄丟了,此次好了,把辛苦寫了一個月的功能全弄丟了。還好我力挽狂瀾幫他恢復了過來。下面咱們分兩種代碼丟失的場景狀況來討論。面試
你使用了git reset --hard commit—id命令,將工做區的提交穿越到你指定的commit裏,這個時候你會發現git log根本沒有記錄這以後的提交記錄,像下面這個樣子,你是否是會很是着急呢?算法
不要太緊張,Git提供了一個命令git reflog
用來記錄你的每一次改變目錄樹的命令,使用好他就能夠很方便的恢復你的提交:編程
剛纔咱們提到一個關鍵字目錄樹,那麼什麼是目錄樹呢?後端
咱們的主線每每是一根直線,多一個分支至關於多一個分叉,無數分支縱橫交錯就像一顆樹狀的結構,因此咱們稱之爲目錄樹。commit rebase reset merge
這些都是改變目錄樹的操做。數據結構
commit
記錄和 reset rebase merge
的操做 咱們能夠看到git reflog
前面的就是commit id
,如今咱們就能夠用以前介紹過的方法來回滾版本了再舉一個例子,經過上面的git reflog打印出來的記錄,咱們記住最後兩個提交的commit id和提交說明分別是00:50和18:51,咱們來使用git reset --hard commit—id去到18:51,這個時候 00:50的提交就沒有了,就算git log也看不見。而後咱們再經過咱們記住的commit id就能夠回滾回去了!app
上圖的步驟爲:ui
git reflog
返回的結果,用git reset --hard commit_id
回退到856a740
這個版本git log -1
看近一行的日誌,能夠看到目前回到了856a740
這個版本,也就是上一個版本git reflog
的結果,用git reset --hard 35b66ed
跑回最新的此次提交git log -2
看到兩次提交的日誌,咱們就這麼再穿梭過來了,就是這麼爽可是咱們若是隻是想把此提交給找回來,恢復他,那仍是不要用reset
的方式,能夠用git cherry-pick commitid
單獨取一個commit到當前分支或者用merge
來作合併。
若是你的代碼文件沒有commit過,就被手賤刪除掉了或者也是被reset --hard
的時候搞沒了。
這就不只僅是用一個git reflog命令就能夠簡單找回來的,但只要你之前有作過add
的操做把他放到過暫存區,咱們就能夠把他找回來。什麼?你連add都沒有操做過那就只能開始準備新一輪的面試了。
先來建立一個災難現場。
lose_file.txt
的文件並寫入內容my lose message
,並使用git add把他加到暫存區git reset --hard 35b66ed8
用丟棄一切修改的方式來使如今的工做區恢復到35b66ed8
版本,由於還沒提交因此也就是恢復到當前的(head
)版本。status
和ls
再看,這個叫lose_file.txt
的文件真的沒了,完蛋了,第一反應使用剛剛學到的命令git reflog
會發現根本就很差使,那如今只能去準備跑路了呢?不慌,讓咱們進入下一節核心命令:git fsck --lost-found
,他會經過一些神奇的方式把歷史操做過的文件以某種算法算出來加到.git/lost-found
文件夾裏,輸出的記錄就像下面這個樣子。
咱們能夠看到這裏有blob、commit、tree
類型的數據,還有tag
等類型的。他們是什麼含義呢?
來,咱們都是大神固然要學學git底層存儲方式,以下圖:
commit
數據結構在每次提交以後都會生成一個,當咱們進行commit
以後,首先會建立一個commit
組件,以後建立一個tree
組件,把全部的文件信息都儲存在裏面,每一個blob
表明一個文件,均可以在tree
裏找到blob
組件並不會對文件信息進行存儲,而是隻對文件的內容進行記錄,文件信息存儲在tree裏言歸正傳,咱們來看看怎麼恢復剛剛git reset --hard後,不見了的lose_file.txt
文件。
在上面執行完git fsck --lost-found
命令,返回的第一行blob
咱們使用git show命令來看看他的內容
正好內容就是lose_file.txt本來的內容,就是咱們丟失的文件內容,這樣就找回來了!
咱們再來看看上圖中的commit
和commit下的tree內容,能夠看到他們之間的層級關係以下:
git cat-file -p
能夠看到commit的內容,能夠選擇把這個commit合併到咱們的分支裏,仍是reset merge rebase cherry-pick
這些命令來合commit
git ls-tree
列出tree下面的文件名和id
的記錄信息,而後就能夠根據blob的id來恢復文件了若是你發現執行git fsck --lost-found
的輸出也找不到你想要的,那麼只能祭出終極命令來輸出近期修改的文件了,以下:
find .git/objects -type f | xargs ls -lt | sed 3q
這個命令,他的含義是查找.git/objects文件夾下的普通文件 按照時間排序後 打印在終端裏 sed 3q 是打印3行 sed 100q 是打印100行,隨你喜歡。git cat-file -t
7f5965523d2b9e850b39eb46e8e0f7c5755f6719
就能看見文件類型 把最後一個/去掉 複製從objects/ 後面的全部東西放在-t後面git cat-file -p id
就能看見文件內容,是否是很爽,你再用高超的linux技巧操做一下,就能夠批量打印出所有文件的類型啦通過一番操做之後實習生【悲郭】終於不用再背鍋了,咱們來總結一下:
1. 提交過的就用命令git reflog
來查詢提交記錄找回
2. 未提交可是git add過的就用git fsck --lost-found來生成丟失文件記錄來找回。
3. 沒找回成功就用用find .git/objects -type f | xargs ls -lt | sed 3q
這個命令來輸出近期修改的文件找回。
代碼恢復的前提是要保證你的項目根目錄下.git文件夾是完整的,要是手動刪除了裏面的一些東西那就真完了。還要保證一點,你的代碼之前是有過git追蹤,最少add過!
只要有一我的能得到幫助,小熊就會繼續努力
喜歡就讓咱們一塊兒玩耍吧