Git
章節 ▾ 第二版

2.3 Git 基礎 - 檢視提交歷史

檢視提交歷史

在您建立數個提交之後,或者如果您複製了一個具有現有提交歷史的儲存庫,您可能會想回頭看看發生了什麼事。執行此操作最基本且功能強大的工具是 git log 命令。

這些範例使用一個名為「simplegit」的非常簡單的專案。要取得該專案,請執行

$ git clone https://github.com/schacon/simplegit-progit

當您在此專案中執行 git log 時,您應該會得到類似以下的輸出

$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    Change version number

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    Remove unnecessary test

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 10:31:28 2008 -0700

    Initial commit

預設情況下,不帶任何參數的 git log 會以相反的時間順序列出該儲存庫中所做的提交;也就是說,最新的提交會最先顯示。如您所見,此命令會列出每個提交的 SHA-1 檢查碼、作者的姓名和電子郵件、寫入日期以及提交訊息。

git log 命令提供了大量且多樣的選項,可讓您精確地顯示您要尋找的內容。在這裡,我們將向您展示一些最常用的選項。

其中一個更有幫助的選項是 -p--patch,它會顯示每個提交中所引入的差異(_patch_ 輸出)。您也可以限制顯示的記錄項目數量,例如使用 -2 只顯示最後兩個項目。

$ git log -p -2
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    Change version number

diff --git a/Rakefile b/Rakefile
index a874b73..8f94139 100644
--- a/Rakefile
+++ b/Rakefile
@@ -5,7 +5,7 @@ require 'rake/gempackagetask'
 spec = Gem::Specification.new do |s|
     s.platform  =   Gem::Platform::RUBY
     s.name      =   "simplegit"
-    s.version   =   "0.1.0"
+    s.version   =   "0.1.1"
     s.author    =   "Scott Chacon"
     s.email     =   "schacon@gee-mail.com"
     s.summary   =   "A simple gem for using Git in Ruby code."

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    Remove unnecessary test

diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index a0a60ae..47c6340 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -18,8 +18,3 @@ class SimpleGit
     end

 end
-
-if $0 == __FILE__
-  git = SimpleGit.new
-  puts git.show
-end

此選項會顯示相同的資訊,但在每個項目之後直接加上 diff。這對於程式碼審查或快速瀏覽協作者新增的一系列提交期間發生的事情非常有幫助。您也可以使用 git log 的一系列摘要選項。例如,如果您想查看每個提交的一些簡短統計資訊,您可以使用 --stat 選項

$ git log --stat
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Mon Mar 17 21:52:11 2008 -0700

    Change version number

 Rakefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 16:40:33 2008 -0700

    Remove unnecessary test

 lib/simplegit.rb | 5 -----
 1 file changed, 5 deletions(-)

commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date:   Sat Mar 15 10:31:28 2008 -0700

    Initial commit

 README           |  6 ++++++
 Rakefile         | 23 +++++++++++++++++++++++
 lib/simplegit.rb | 25 +++++++++++++++++++++++++
 3 files changed, 54 insertions(+)

如您所見,--stat 選項會在每個提交項目下方印出已修改檔案的清單、已變更的檔案數量,以及在這些檔案中新增和移除的行數。它也會在最後放置資訊摘要。

另一個非常有用的選項是 --pretty。此選項會將日誌輸出變更為預設格式以外的格式。您可以使用一些預先建置的選項值。此選項的 oneline 值會在單行上印出每個提交,如果您正在查看大量提交,這非常有用。此外,shortfullfuller 值會以大致相同的格式顯示輸出,但資訊量分別較少或較多

$ git log --pretty=oneline
ca82a6dff817ec66f44342007202690a93763949 Change version number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 Remove unnecessary test
a11bef06a3f659402fe7563abf99ad00de2209e6 Initial commit

最有趣的選項值是 format,它允許您指定自己的日誌輸出格式。當您產生用於機器解析的輸出時,這特別有用,因為您明確指定了格式,所以您知道它不會隨著 Git 的更新而變更

$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : Change version number
085bb3b - Scott Chacon, 6 years ago : Remove unnecessary test
a11bef0 - Scott Chacon, 6 years ago : Initial commit

git log --pretty=format 的有用指定符 列出了 format 可以採用的一些更有用的指定符。

表 1. git log --pretty=format 的有用指定符
指定符 輸出描述

%H

提交雜湊值

%h

縮寫的提交雜湊值

%T

樹狀結構雜湊值

%t

縮寫的樹狀結構雜湊值

%P

父雜湊值

%p

縮寫的父雜湊值

%an

作者姓名

%ae

作者電子郵件

%ad

作者日期 (格式遵從 --date=選項)

%ar

作者日期,相對時間

%cn

提交者名稱

%ce

提交者電子郵件

%cd

提交者日期

%cr

提交者日期,相對時間

%s

主旨

您可能想知道作者提交者之間的區別。作者是最初撰寫工作的人,而提交者是最後應用該工作的人。因此,如果您將修補程式發送到專案,而其中一位核心成員應用了該修補程式,則您們兩人都會獲得功勞 - 您作為作者,而核心成員作為提交者。我們將在分散式 Git中更詳細地介紹這種區別。

onelineformat 選項值與另一個名為 --graphlog 選項特別有用。此選項會新增一個漂亮的 ASCII 圖表,顯示您的分支和合併歷史記錄

$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 Ignore errors from SIGCHLD on trap
*  5e3ee11 Merge branch 'master' of https://github.com/dustin/grit.git
|\
| * 420eac9 Add method for getting the current branch
* | 30e367c Timeout code and tests
* | 5a09431 Add timeout protection to grit
* | e1193f8 Support for heads with slashes in them
|/
* d6016bc Require time for xmlschema
*  11d191e Merge branch 'defunkt' into local

當我們在下一章中介紹分支和合併時,這種輸出類型將變得更有趣。

這些只是 git log 的一些簡單輸出格式選項 - 還有很多其他選項。 git log 的常用選項列出了我們目前介紹的選項,以及其他一些可能有用的常用格式選項,以及它們如何變更 log 命令的輸出。

表 2. git log 的常用選項
選項 描述

-p

顯示每次提交引入的修補程式。

--stat

顯示每次提交中修改的檔案的統計資訊。

--shortstat

僅顯示 --stat 命令中的已變更/插入/刪除的行。

--name-only

在提交資訊之後顯示修改的檔案清單。

--name-status

顯示受影響的檔案清單,以及新增/修改/刪除的資訊。

--abbrev-commit

僅顯示 SHA-1 校驗和的前幾個字元,而不是全部 40 個字元。

--relative-date

以相對格式顯示日期(例如,「2 週前」),而不是使用完整日期格式。

--graph

在日誌輸出旁邊顯示分支和合併歷史記錄的 ASCII 圖表。

--pretty

以其他格式顯示提交。選項值包括 onelineshortfullfullerformat(您可以在其中指定自己的格式)。

--oneline

--pretty=oneline --abbrev-commit 一起使用的簡寫。

限制日誌輸出

除了輸出格式選項外,git log 還採用許多有用的限制選項;也就是說,讓您僅顯示提交子集的選項。您已經看到了一個這樣的選項 - -2 選項,它僅顯示最後兩個提交。實際上,您可以執行 -<n>,其中 n 是任何整數以顯示最後 n 個提交。實際上,您不太可能經常使用它,因為 Git 預設會透過分頁器管道傳送所有輸出,因此您一次只會看到一頁日誌輸出。

但是,時間限制選項(例如 --since--until)非常有用。例如,此命令會取得過去兩週內所做的提交清單

$ git log --since=2.weeks

此命令適用於許多格式 - 您可以指定特定日期,例如 "2008-01-15",或相對日期,例如 "2 years 1 day 3 minutes ago"

您也可以篩選清單,以篩選符合某些搜尋條件的提交。--author 選項可讓您根據特定作者篩選,而 --grep 選項可讓您在提交訊息中搜尋關鍵字。

注意

您可以指定多個 --author--grep 搜尋條件,這會將提交輸出限制為符合任何 --author 模式和任何 --grep 模式的提交;但是,新增 --all-match 選項會進一步將輸出限制為僅符合所有 --grep 模式的那些提交。

另一個非常有用的篩選器是 -S 選項(俗稱 Git 的「鶴嘴鋤」選項),它會取得一個字串,並且僅顯示那些變更該字串出現次數的提交。例如,如果您想找到最後一個新增或刪除對特定函式的參考的提交,則可以呼叫

$ git log -S function_name

作為篩選器傳遞給 git log 的最後一個非常有用的選項是路徑。如果您指定目錄或檔案名稱,您可以將日誌輸出限制為對這些檔案進行變更的提交。這永遠是最後一個選項,通常以雙破折號 (--) 開頭,以將路徑與選項分開

$ git log -- path/to/file

限制 git log 輸出的選項中,我們將列出這些選項和其他一些常用選項供您參考。

表 3. 限制 git log 輸出的選項
選項 描述

-<n>

僅顯示最後 n 個提交。

--since--after

將提交限制為在指定日期之後所做的提交。

--until--before

將提交限制為在指定日期之前所做的提交。

--author

僅顯示作者條目符合指定字串的提交。

--committer

僅顯示提交者條目符合指定字串的提交。

--grep

僅顯示提交訊息包含該字串的提交。

-S

僅顯示新增或刪除符合該字串的程式碼的提交。

例如,如果您想查看 2008 年 10 月由 Junio Hamano 提交的,且不是合併提交的 Git 原始程式碼歷程記錄中修改測試檔的哪些提交,您可以執行如下命令

$ git log --pretty="%h - %s" --author='Junio C Hamano' --since="2008-10-01" \
   --before="2008-11-01" --no-merges -- t/
5610e3b - Fix testcase failure when extended attributes are in use
acd3b9e - Enhance hold_lock_file_for_{update,append}() API
f563754 - demonstrate breakage of detached checkout with symbolic link HEAD
d1a43f2 - reset --hard/read-tree --reset -u: remove unmerged new paths
51a94af - Fix "checkout --track -b newbranch" on detached HEAD
b0ad11e - pull: allow "git pull origin $something:$current_branch" into an unborn branch

在 Git 原始程式碼歷程記錄中的將近 40,000 個提交中,此命令會顯示符合這些條件的 6 個提交。

提示
防止顯示合併提交

根據您儲存庫中使用的流程,您的日誌歷程記錄中相當大比例的提交可能只是合併提交,這些提交通常資訊量不大。若要防止顯示合併提交而使您的日誌歷程記錄雜亂無章,只需新增 log 選項 --no-merges

scroll-to-top