Git - 檢視提交歷史
本文講解使用 git 等工具檢視提交歷史的幾種方式。
git log
在我理解中,實際上後面講的各種方法都是基於 git log 命令列工具,且對於程式設計師而言,命令列才是正統;
預設不用任何引數的話,git log 會按提交時間列出所有的更新,最近的更新排在最上面。每次更新都有一個 SHA-1 校驗和、作者的名字和電子郵件地址、提交時間,最後縮排一個段落顯示提交說明。git log 命令列會預設開啟一個 vim 編輯器,輸入 :q
退出檢視。
常用選項
-p
選項展開顯示每次提交的內容差異;
-2
則僅顯示最近的兩次更新;
--word-diff
選項。可以將其新增到 git log -p 命令的後面,從而獲取單詞層面上的對比。在書籍、論文這種很大的文字檔案上進行對比的時候;
--stat
作者(author)和提交者(committer)的差別,作者指的是實際作出修改的人,提交者指的是最後將此工作成果提交到倉庫的人。所以,當你為某個專案釋出補丁,然後某個核心成員將你的補丁併入專案時,你就是作者,而那個核心成員就是提交者。
示例
檢視 Git 倉庫中,2018 年 9 月期間,Junio Hamano 提交的但未合併的測試指令碼(位於專案的 t/ 目錄下的檔案),命令:
git log --pretty="%h - %s" --author=gitster --since="2018-09-01" --before="2018-09-30" --no-merges -- t/
git log -p -2
選項除了顯示基本資訊之外,還在附帶每次 commit 的變化。常用於程式碼審查,或者快速瀏覽某個搭檔提交的 commit 的變化。
git log -U1 --word-diff
這裡並沒有平常看到的新增行或者刪除行的資訊。這裡的對比顯示在行間。新增加的單詞被 {+ +} 括起來,被刪除的單詞被 [- -] 括起來。在進行單詞層面的對比的時候,你可能希望上下文( context )行數從預設的 3 行,減為 1 行,那麼可以使用 -U1 選項。
git log --stat
每個提交都列出修改過的檔案,以及其中新增和移除的行數,並在最後列出所有增減行數小計。 還有個常用的 --pretty 選項,可以指定使用完全不同於預設格式的方式展示提交歷史。比如用 oneline 將每個提交放在一行顯示,這在提交數很大時非常有用。另外還有 short,full 和 fuller 可以用,展示的資訊或多或少有些不同。
用 oneline 或 format 時結合 --graph 選項,可以看到開頭多出一些 ASCII 字串表示的簡單圖形,形象地展示了每個提交所在的分支及其分化衍合情況。在我們之前提到的 Grit 專案倉庫中可以看到:
git log --pretty=format:"%h %s" --graph
git log --pretty=oneline
format,可以定製要顯示的記錄格式,這樣的輸出便於後期程式設計提取分析:
git log --pretty=format:"%h - %an, %ar : %s"
列出常用的格式佔位符寫法及其代表的意義。
選項 | 說明 |
---|---|
%H | 提交物件(commit)的完整雜湊字串 |
%h | 提交物件的簡短雜湊字串 |
%T | 樹物件(tree)的完整雜湊字串 |
%t | 樹物件的簡短雜湊字串 |
%P | 父物件(parent)的完整雜湊字串 |
%p | 父物件的簡短雜湊字串 |
%an | 作者(author)的名字 |
%ae | 作者的電子郵件地址 |
%ad | 作者修訂日期(可以用 -date= 選項定製格式) |
%ar | 作者修訂日期,按多久以前的方式顯示 |
%cn | 提交者(committer)的名字 |
%ce | 提交者的電子郵件地址 |
%cd | 提交日期 |
%cr | 提交日期,按多久以前的方式顯示 |
%s | 提交說明 |
列出所有最近兩週內的提交: git log --since=2.weeks
or git log --since=2weeks
還可以給出若干搜尋條件,列出符合的提交。用 --author 選項顯示指定作者的提交,用 --grep 選項搜尋提交說明中的關鍵字。(如果要得到同時滿足這兩個選項搜尋條件的提交,就必須用 --all-match 選項。否則滿足任意一個條件的提交都會被匹配出來)
git log選項是路徑(path),如果只關心某些檔案或者目錄的歷史提交,可以在 git log 選項的最後指定它們的路徑。因為是放在最後位置上的選項,所以用兩個短劃線(–)隔開之前的選項和後面限定的路徑名。
彙總表格如下
選項 | 說明 |
---|---|
-p |
按補丁格式顯示每個更新之間的差異。 |
--word-diff |
按 word diff 格式顯示差異。 |
--stat |
顯示每次更新的檔案修改統計資訊。 |
--shortstat |
只顯示 --stat 中最後的行數修改新增移除統計。 |
--name-only |
僅在提交資訊後顯示已修改的檔案清單。 |
--name-status |
顯示新增、修改、刪除的檔案清單。 |
--abbrev-commit |
僅顯示 SHA-1 的前幾個字元,而非所有的 40 個字元。 |
--relative-date |
使用較短的相對時間顯示(比如,“2 weeks ago”)。 |
--graph |
顯示 ASCII 圖形表示的分支合併歷史。 |
--pretty |
使用其他格式顯示歷史提交資訊。可選項包括 oneline,short,full,fuller 和 format(後跟指定格式)。 |
--oneline |
--pretty=oneline --abbrev-commit 的簡化用法。 |
-(n) |
僅顯示最近的 n 條提交;不常用,Git 在輸出所有提交時會自動呼叫分頁程式(less),要看更早的更新只需翻到下頁即可。 |
--since, --after |
僅顯示指定時間之後的提交。 |
--until, --before |
僅顯示指定時間之前的提交。 |
--author |
僅顯示指定作者相關的提交。 |
--committer |
僅顯示指定提交者相關的提交。 |
gitk
安裝 Git 之後就自帶 gitk 圖形化工具,用 Tcl/Tk 寫成,相當於 git log 命令的視覺化版本,凡是 git log 可以用的選項也都能用在 gitk 上。在 git 程式碼庫下面 輸入 gitk 命令就可以開啟這個圖形化工具。
IDEA——version control——log
自從使用 IDEA 之後,基本上也不會再去定位到本地的程式碼倉庫,然後右鍵開啟一個命令列視窗,輸入命令 git log 或者 gitk,而是就地直接使用 IDEA 的 version control——log 功能,IDEA 預設也是可以看到 graph 形式的 git log,而且也支援各種條件搜尋,釋出簡潔地看到提交歷史。
比如最前面的編輯框可以輸入查詢條件,隨後的 regex 或者 match case 表示查詢條件的匹配模式;
隨後的 branch 可以選擇哪個 branch 的提交歷史記錄;
再往後的 user,date,path,以及其他足夠日常開發應用。
source tree
試用過 source tree,比 Tortoise Git 更專業,畢竟是收費軟體,把版本控制管理做到極致,破解方法參考版本控制工具 Git 使用筆記。一般情況下,只要你熟悉 Git 的原理之後,就不需要所謂的圖形化工具,也就不需要 source tree 這樣的專業工具;不過對於有些版本控制很嚴格的專案,比如實施 Git Flow 開發模式的專案,branch 或者 tag 就會比較複雜,此時 source tree 就會派上用場。
附圖 Git Flow
IDEA 甚至提供 Git Flow 外掛
Git Flow 參考:
參考1
參考2
git log vs git reflog
git reflog
reference log,檢視引用日誌。
參考git reflog
裡面提到:
記錄的是本地倉庫的所有 git 操作,比如 git pull
都會記錄下來。原文:record when the tips of branches and other references were updated in the local repository.
引用日誌資訊只存在於本地——這是一個記錄你在你自己的倉庫裡做過什麼的日誌。其他人拷貝的倉庫裡的引用日誌不會和你的相同;而你新克隆一個倉庫的時候,引用日誌是空的,因為你在倉庫裡還沒有操作。git show [email protected]{2.months.ago}
這條命令只有在你克隆一個專案至少兩個月時才會有用——如果你是五分鐘前克隆的倉庫,那麼它將不會有結果返回。
git reflog show
accepts any of the options accepted by git log
。大意就是 git reflog show
命令是 git log
命令的超集。
其餘的子命令包括:
git reflog [show] [log-options] [<ref>]
git reflog expire [--expire=<time>] [--expire-unreachable=<time>]
[--rewrite] [--updateref] [--stale-fix]
[--dry-run | -n] [--verbose] [--all | <refs>…]
git reflog delete [--rewrite] [--updateref]
[--dry-run | -n] [--verbose] [email protected]{specifier}…
git reflog exists <ref>
兩者的區別:
git log:commit 的版本日誌,版本回退後,使用git log 看不到回退版本號之後的版本記錄;
git reflog:使用git 命令進行操作的日誌,包括當前步驟所在哪個版本(一個commit 產生一個版本,指定版本回退只能回退到該commit) 以及操作的具體內容;版本回退後,仍然可以看到所有的版本記錄,檢視每個操作步驟所在的版本,可以根據版本號自由前進後退。
總之:如果在回退以後又想再次回到之前的版本,git reflog 可以檢視所有分支的所有操作記錄(包括commit和reset的操作),包括已經被刪除的commit記錄,git log則不能察看已經刪除了的commit記錄