回到過去
背景
現在你已經掌握git
的基本操作了,檔案發生更改首先使用 git add
新增更改,然後 git commit
提交全部更改,當本地檔案再次發生更改時,仍然需要git add
和 git commit
兩步操作,中途如何想檢視檔案是否發生更改,使用git status
檢視版本庫狀態,git diff
命令幫助我們檢視更改詳情.
像這樣重複的操作其實每次都會產生一個快照,用於儲存檔案狀態,只不過這個快照不是完整的檔案,被稱為提交或者版本commit
.一旦發生意外,假如檔案修改亂了或者誤刪了檔案,我們可以從最近的一個 commit
中進行恢復,然後繼續工作,這就是git
管理的好處之一.
每一次重大更新或者你認為比較重要的時刻,我們總會留作紀念,新增些什麼特殊標記來區分平時的提交,還記得我們每次提交都會新增備註嗎?git commit -m <remark>
這條命令現在就可以大顯身手了,我們現在要做的就是找到我們提交的歷史記錄,而歷史記錄中有我們提交的詳情,這樣即使過了一個月或者更長時間,我們也能清楚知道當時的情景!
檢視提交歷史記錄 git log
,接下來我們趕緊試一下吧
$ git log
commit 36f234a60d858871f040cb0d7ca3e78251df82f7 (HEAD -> master)
Author: snowdreams1006 <snowdreams1006@163.com>
Date: Thu Mar 7 22:19:00 2019 +0800
add understand how git control version
commit 2006f72ffe2ce2278b5974313b8598847cf445e4
Author: snowdreams1006 <snowdreams1006@163.com>
Date: Tue Mar 5 13:27:46 2019 +0800
add 3 files.
commit eaa4850070354ae987dc5108a9fd57fda9d64730
Author: snowdreams1006 <snowdreams1006@163.com>
Date: Tue Mar 5 12:18:57 2019 +0800
add git init
commit 6ad8956bc09a6a62c731711eabe796690aa6471c
Author: snowdreams1006 <snowdreams1006@163.com>
Date: Tue Mar 5 12:17:51 2019 +0800
add test.txt
複製程式碼
git log
命令預設顯示最近到最遠的提交歷史,這一點也很好理解,畢竟我們是在命令列操作,輸入git log
完畢後自然先要定位到命令處,看到最新提交記錄方便我們確認是否符合我們預期,還有一點就是如果提交歷史過多,從頭開始到最新提交記錄豈不是眼花繚亂,簡直不敢想象啊!
下面以最新的一次提交 commit
為例,簡單解釋一下輸出內容:
# 提交唯一標示id: 36f234a60d858871f040cb0d7ca3e78251df82f7
commit 36f234a60d858871f040cb0d7ca3e78251df82f7 (HEAD -> master)
# 作者: snowdreams1006 郵箱: <snowdreams1006@163.com>
Author: snowdreams1006 <snowdreams1006@163.com>
# 日期: Thu Mar 7 22:19:00 2019 +0800
Date: Thu Mar 7 22:19:00 2019 +0800
# 提交備註: add understand how git control version
add understand how git control version
複製程式碼
預設輸出內容有點多,不僅有提交 id ,提交備註還有作者時間之類的,由於每個 commit
都如此,這樣一來,滿屏都展示不下,那能不能簡化些呢?
一行顯示提交日誌 ** --pretty=oneline
**,即git log --pretty=oneline
$ git log --pretty=oneline
36f234a60d858871f040cb0d7ca3e78251df82f7 (HEAD -> master) add understand how git control version
2006f72ffe2ce2278b5974313b8598847cf445e4 add 3 files.
eaa4850070354ae987dc5108a9fd57fda9d64730 add git init
6ad8956bc09a6a62c731711eabe796690aa6471c add test.txt
$
複製程式碼
相比無引數git log
,是不是簡短了一些呢? 和之前日誌相比少了作者和時間等資訊,仍然保留提交 id 和提交備註.
因為提交 commit
是 git
的基礎,當然不能省略,而提交備註能夠幫助我們理解commit
的含義,畢竟提交備註使我們自定義的內容,這也是我們為什麼提交時要寫提交備註的原因!
現在我們已經瞭解到版本庫存放了我們的提交,接下來讓我們驗證一下是否能夠回到過去吧!
回到上一個提交,上一個提交自然是相對當前提交而言,只有知道當前提交才能知道上一個提交以及上一個提交的上一個提交.
提交id 36f234a60d858871f040cb0d7ca3e78251df82f7
,那麼上一個提交HEAD^
,上上一個提交是HEAD^^
.如果此時我想回到往上數100個版本,那麼是不是可以這麼寫?
HEAD^^^^...^^^
其中^
有100個,如果需要手動打出100個^
的話,那麼絕對是瘋了!
既然有這種相對定位方式,自然也有絕對定位方式,用絕對定位方式解決就是這樣: HEAD~100
$ git log
commit 36f234a60d858871f040cb0d7ca3e78251df82f7 (HEAD -> master)
Author: snowdreams1006 <snowdreams1006@163.com>
Date: Thu Mar 7 22:19:00 2019 +0800
add understand how git control version
複製程式碼
**回到上一個版本 git reset --hard HEAD^
**
在操作之前我們先看一下當前檔案 test.txt
的內容:
$ cat test.txt
git test
git init
git diff
understand how git control version
複製程式碼
現在讓我們開始回到過去,執行 git reset --hard HEAD^
命令:
$ git reset --hard HEAD^
HEAD is now at 2006f72 add 3 files.
$
複製程式碼
現在讓我們再看一下,test.txt
的內容有沒有被還原:
$ cat test.txt
git test
git init
複製程式碼
果然被還原了!這就是git
的神奇之處,說明我們已經能夠回到過去了!
現在我們先用git log
檢視下提交歷史:
$ git log
commit 2006f72ffe2ce2278b5974313b8598847cf445e4 (HEAD -> master)
Author: snowdreams1006 <snowdreams1006@163.com>
Date: Tue Mar 5 13:27:46 2019 +0800
add 3 files.
commit eaa4850070354ae987dc5108a9fd57fda9d64730
Author: snowdreams1006 <snowdreams1006@163.com>
Date: Tue Mar 5 12:18:57 2019 +0800
add git init
commit 6ad8956bc09a6a62c731711eabe796690aa6471c
Author: snowdreams1006 <snowdreams1006@163.com>
Date: Tue Mar 5 12:17:51 2019 +0800
add test.txt
$
複製程式碼
和上次相比,少了一條提交記錄:
commit 36f234a60d858871f040cb0d7ca3e78251df82f7 (HEAD -> master)
Author: snowdreams1006 <snowdreams1006@163.com>
Date: Thu Mar 7 22:19:00 2019 +0800
add understand how git control version
複製程式碼
這樣是正常的,畢竟你已經處於 過去 了,當然看不到 未來 的提交記錄.
正如影視穿越劇那樣,主人公意外穿越過去,總是想要回到未來,怎麼辦,沒有法器沒有未來的確切目標怎麼行?!
git
的穿越劇也需要這樣一種法器,能準確告訴時光機把我們帶到具體的那個時間點,當然這個時間點不一定是未來時刻,過去時刻也行,反正就是一個準確的座標.
聰明的你肯定已經猜測到這個任務是由commit
擔任的,所有我們現在要找到未來的時間點,也就是commit
id,就是那一長串 hash 字串.
只要當前命令列視窗還沒有關閉,慢慢往上翻,總是能找到當初我們的穿越點commit
的,即36f234a60d858871f040cb0d7ca3e78251df82f7
**回到當初提交 git reset --hard <commit>
**
萬事俱備只欠東風,已經成功定位到未來座標,等待穿越到未來!
$ git reset --hard 36f234a60d858871f040cb0d7ca3e78251df82f7
HEAD is now at 36f234a add understand how git control version
$
複製程式碼
現在我們再次檢視 test.txt
內容:
$ cat test.txt
git test
git init
git diff
understand how git control versi
複製程式碼
果然成功穿越回到未來!
上述穿越回到未來的場景是我們知道目標 commit
,也就是在當前命令列視窗沒有關閉的情況下,手動查詢穿越點 commit
.那如果命令列視窗已關閉或者沒辦法通過查閱歷史命令來定位穿越點 commit
情況下怎麼辦呢?
這種情況下也是有補救措施的,git
提供了命令歷史 git reflog
,記錄了我們操作的命令歷史.
**翻閱歷史命令 git reflog
**
$ git reflog
36f234a (HEAD -> master) HEAD@{0}: reset: moving to 36f234a60d858871f040cb0d7ca3e78251df82f7
2006f72 HEAD@{1}: reset: moving to HEAD^
36f234a (HEAD -> master) HEAD@{2}: commit: add understand how git control version
2006f72 HEAD@{3}: commit: add 3 files.
eaa4850 HEAD@{4}: commit: add git init
6ad8956 HEAD@{5}: commit (initial): add test.txt
複製程式碼
確實記錄了我們操作的關鍵命令,從上述輸出結果可以看出,穿越點 commit
正是36f234a60d858871f040cb0d7ca3e78251df82f7
,剩下的事情應該不必多說了吧!
小結
HEAD
是當前提交的指標,指向的提交就是當前提交,上一個提交是HEAD^
,上上個提交是HEAD^^
,前100個提交是HEAD~100
.git log
檢視提交歷史,git log --pretty=oneline
簡短化輸出提交歷史.git reflog
檢視命令歷史,以便我們重拾關鍵步驟資訊.git reset --hard <commit>
穿越到指定提交,比如上一個提交就是git reset --hard HEAD^
.