# 查看提交歷史
在提交了若干更新,又或者克隆了某個項目之后,你也許想回顧下提交歷史.完成這個任務最簡單而又有效的工具是 `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
changed the version number
commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 16:40:33 2008 -0700
removed unnecessary test
commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 10:31:28 2008 -0700
first commit
~~~
默認不用任何參數的話,`git log` 會按提交時間列出所有的更新,最近的更新排在最上面。正如你所看到的,這個命令會列出每個提交的 SHA-1 校驗和、作者的名字和電子郵件地址、提交時間以及提交說明。
`git log` 有許多選項可以幫助你搜尋你所要找的提交,接下來我們介紹些最常用的。
一個常用的選項是 `-p`,用來顯示每次提交的內容差異。你也可以加上 `-2` 來僅顯示最近兩次提交:
~~~
$ git log -p -2
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the 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
removed 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
\ No newline at end of file
~~~
該選項除了顯示基本信息之外,還在附帶了每次 commit 的變化。當進行代碼審查,或者快速瀏覽某個搭檔提交的 commit 所帶來的變化的時候,這個參數就非常有用了。你也可以為 `git log` 附帶一系列的總結性選項。比如說,如果你想看到每次提交的簡略的統計信息,你可以使用 `--stat` 選項:
~~~
$ git log --stat
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the 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
removed 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
first commit
README | 6 ++++++
Rakefile | 23 +++++++++++++++++++++++
lib/simplegit.rb | 25 +++++++++++++++++++++++++
3 files changed, 54 insertions(+)
~~~
正如你所看到的,`--stat` 選項在每次提交的下面列出額所有被修改過的文件、有多少文件被修改了以及被修改過的文件的哪些行被移除或是添加了。在每次提交的最后還有一個總結。
另外一個常用的選項是 `--pretty`。這個選項可以指定使用不同于默認格式的方式展示提交歷史。這個選項有一些內建的子選項供你使用。比如用 `oneline` 將每個提交放在一行顯示,查看的提交數很大時非常有用。另外還有 `short`,`full` 和 `fuller` 可以用,展示的信息或多或少有些不同,請自己動手實踐一下看看效果如何。
~~~
$ git log --pretty=oneline
ca82a6dff817ec66f44342007202690a93763949 changed the version number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test
a11bef06a3f659402fe7563abf99ad00de2209e6 first commit
~~~
但最有意思的是 format,可以定制要顯示的記錄格式。這樣的輸出對后期提取分析格外有用?—?因為你知道輸出的格式不會隨著Git的更新而發生改變:
~~~
$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : changed the version number
085bb3b - Scott Chacon, 6 years ago : removed unnecessary test
a11bef0 - Scott Chacon, 6 years ago : first commit
~~~
[Table?2-1](#) 列出了常用的格式占位符寫法及其代表的意義。
<table id="pretty_format"><caption><span class="label">Table 2-1. </span><code>git log --pretty=format</code> 常用的選項</caption><thead><tr><th width="20%">選項</th><th>說明</th></tr></thead><tbody><tr><td><p><code>%H</code></p></td><td><p>提交對象(commit)的完整哈希字串</p></td></tr><tr><td><p><code>%h</code></p></td><td><p>提交對象的簡短哈希字串</p></td></tr><tr><td><p><code>%T</code></p></td><td><p>樹對象(tree)的完整哈希字串</p></td></tr><tr><td><p><code>%t</code></p></td><td><p>樹對象的簡短哈希字串</p></td></tr><tr><td><p><code>%P</code></p></td><td><p>父對象(parent)的完整哈希字串</p></td></tr><tr><td><p><code>%p</code></p></td><td><p>父對象的簡短哈希字串</p></td></tr><tr><td><p><code>%an</code></p></td><td><p>作者(author)的名字</p></td></tr><tr><td><p><code>%ae</code></p></td><td><p>作者的電子郵件地址</p></td></tr><tr><td><p><code>%ad</code></p></td><td><p>作者修訂日期(可以用 --date= 選項定制格式)</p></td></tr><tr><td><p><code>%ar</code></p></td><td><p>作者修訂日期,按多久以前的方式顯示</p></td></tr><tr><td><p><code>%cn</code></p></td><td><p>提交者(committer)的名字</p></td></tr><tr><td><p><code>%ce</code></p></td><td><p>提交者的電子郵件地址</p></td></tr><tr><td><p><code>%cd</code></p></td><td><p>提交日期</p></td></tr><tr><td><p><code>%cr</code></p></td><td><p>提交日期,按多久以前的方式顯示</p></td></tr><tr><td><p><code>%s</code></p></td><td><p>提交說明</p></td></tr></tbody></table>
你一定奇怪 *作者* 和 *提交者* 之間究竟有何差別,其實作者指的是實際作出修改的人,提交者指的是最后將此工作成果提交到倉庫的人。所以,當你為某個項目發布補丁,然后某個核心成員將你的補丁并入項目時,你就是作者,而那個核心成員就是提交者。我們會在 [Chapter?5](#) 再詳細介紹兩者之間的細微差別。
當 oneline 或 format 與另一個 `log` 選項 `--graph` 結合使用時尤其有用。這個選項添加了一些ASCII字符串來形象地展示你的分支、合并歷史:
~~~
$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 ignore errors from SIGCHLD on trap
* 5e3ee11 Merge branch 'master' of git://github.com/dustin/grit
|\
| * 420eac9 Added a 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` 命令支持的選項。[Table?2-2](#) 列出了我們目前涉及到的和沒涉及到的選項,已經它們是如何影響 log 命令的輸出的:
<table id="log_options"><caption><span class="label">Table 2-2. </span><code>git log</code> 的常用選項</caption><thead><tr><th width="20%">選項</th><th>說明</th></tr></thead><tbody><tr><td><p><code>-p</code></p></td><td><p>按補丁格式顯示每個更新之間的差異。</p></td></tr><tr><td><p><code>--stat</code></p></td><td><p>顯示每次更新的文件修改統計信息。</p></td></tr><tr><td><p><code>--shortstat</code></p></td><td><p>只顯示 --stat 中最后的行數修改添加移除統計。</p></td></tr><tr><td><p><code>--name-only</code></p></td><td><p>僅在提交信息后顯示已修改的文件清單。</p></td></tr><tr><td><p><code>--name-status</code></p></td><td><p>顯示新增、修改、刪除的文件清單。</p></td></tr><tr><td><p><code>--abbrev-commit</code></p></td><td><p>僅顯示 SHA-1 的前幾個字符,而非所有的 40 個字符。</p></td></tr><tr><td><p><code>--relative-date</code></p></td><td><p>使用較短的相對時間顯示(比如,“2 weeks ago”)。</p></td></tr><tr><td><p><code>--graph</code></p></td><td><p>顯示 ASCII 圖形表示的分支合并歷史。</p></td></tr><tr><td><p><code>--pretty</code></p></td><td><p>使用其他格式顯示歷史提交信息。可用的選項包括 oneline,short,full,fuller 和 format(后跟指定格式)。</p></td></tr></tbody></table>
## 限制輸出長度
除了定制輸出格式的選項之外,`git log` 還有許多非常實用的限制輸出長度的選項,也就是只輸出部分提交信息。之前你已經看到過 `-2` 了,它只顯示最近的兩條提交,實際上,這是 `-<n>` 選項的寫法,其中的 `n` 可以是任何整數,表示僅顯示最近的若干條提交。不過實踐中我們是不太用這個選項的,Git 在輸出所有提交時會自動調用分頁程序,所以你一次只會看到一頁的內容。
另外還有按照時間作限制的選項,比如 `--since` 和 `--until` 也很有用。例如,下面的命令列出所有最近兩周內的提交:
~~~
$ git log --since=2.weeks
~~~
這個命令可以在多種格式下工作,比如說具體的某一天 `"2008-01-15"`,或者是相對地多久以前 `"2 years 1 day 3 minutes ago"`。
還可以給出若干搜索條件,列出符合的提交。用 `--author` 選項顯示指定作者的提交,用 `--grep` 選項搜索提交說明中的關鍵字。(請注意,如果要得到同時滿足這兩個選項搜索條件的提交,就必須用 `--all-match` 選項。否則,滿足任意一個條件的提交都會被匹配出來)
另一個非常有用的篩選選項是 `-S`,可以列出那些添加或移除了某些字符串的提交。比如說,你想找出添加或移除了某一個特定函數的引用的提交,你可以這樣使用:
~~~
$ git log -Sfunction_name
~~~
最后一個很實用的 `git log` 選項是路徑(path),如果只關心某些文件或者目錄的歷史提交,可以在 git log 選項的最后指定它們的路徑。因為是放在最后位置上的選項,所以用兩個短劃線(--)隔開之前的選項和后面限定的路徑名。
在 [Table?2-3](#) 中列出了常用的選項
<table id="limit_options"><caption><span class="label">Table 2-3. </span>限制 <code>git log</code> 輸出的選項</caption><thead><tr><th width="33%">選項</th><th>說明</th></tr></thead><tbody><tr><td><p><code>-(n)</code></p></td><td><p>僅顯示最近的 n 條提交</p></td></tr><tr><td><p><code>--since</code>, <code>--after</code></p></td><td><p>僅顯示指定時間之后的提交。</p></td></tr><tr><td><p><code>--until</code>, <code>--before</code></p></td><td><p>僅顯示指定時間之前的提交。</p></td></tr><tr><td><p><code>--author</code></p></td><td><p>僅顯示指定作者相關的提交。</p></td></tr><tr><td><p><code>--committer</code></p></td><td><p>僅顯示指定提交者相關的提交。</p></td></tr><tr><td><p><code>--grep</code></p></td><td><p>僅顯示含指定關鍵字的提交</p></td></tr><tr><td><p><code>-S</code></p></td><td><p>僅顯示添加或移除了某個關鍵字的提交</p></td></tr></tbody></table>
來看一個實際的例子,如果要查看 Git 倉庫中,2008 年 10 月期間,Junio Hamano 提交的但未合并的測試文件,可以用下面的查詢命令:
~~~
$ git log --pretty="%h - %s" --author=gitster --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
~~~
在近40000條提交中,上面的輸出僅列出了符合條件的6條記錄。
- 前言
- Scott Chacon 序
- Ben Straub 序
- 獻辭
- 貢獻者
- 引言
- 1. 起步
- 1.1 關于版本控制
- 1.2 Git 簡史
- 1.3 Git 基礎
- 1.4 命令行
- 1.5 安裝 Git
- 1.6 初次運行 Git 前的配置
- 1.7 獲取幫助
- 1.8 總結
- 2. Git 基礎
- 2.1 獲取 Git 倉庫
- 2.2 記錄每次更新到倉庫
- 2.3 查看提交歷史
- 2.4 撤消操作
- 2.5 遠程倉庫的使用
- 2.6 打標簽
- 2.7 Git 別名
- 2.8 總結
- 3. Git 分支
- 3.1 分支簡介
- 3.2 分支的新建與合并
- 3.3 分支管理
- 3.4 分支開發工作流
- 3.5 遠程分支
- 3.6 變基
- 3.7 總結
- 4. 服務器上的 Git
- 4.1 協議
- 4.2 在服務器上搭建 Git
- 4.3 生成 SSH 公鑰
- 4.4 配置服務器
- 4.5 Git 守護進程
- 4.6 Smart HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 第三方托管的選擇
- 4.10 總結
- 5. 分布式 Git
- 5.1 分布式工作流程
- 5.2 向一個項目貢獻
- 5.3 維護項目
- 5.4 總結
- 6. GitHub
- 6.1 賬戶的創建和配置
- 6.2 對項目做出貢獻
- 6.3 維護項目
- 6.4 管理組織
- 6.5 腳本 GitHub
- 6.6 總結
- 7. Git 工具
- 7.1 選擇修訂版本
- 7.2 交互式暫存
- 7.3 儲藏與清理
- 7.4 簽署工作
- 7.5 搜索
- 7.6 重寫歷史
- 7.7 重置揭密
- 7.8 高級合并
- 7.9 Rerere
- 7.10 使用 Git 調試
- 7.11 子模塊
- 7.12 打包
- 7.13 替換
- 7.14 憑證存儲
- 7.15 總結
- 8. 自定義 Git
- 8.1 配置 Git
- 8.2 Git 屬性
- 8.3 Git 鉤子
- 8.4 使用強制策略的一個例子
- 8.5 總結
- 9. Git 與其他系統
- 9.1 作為客戶端的 Git
- 9.2 遷移到 Git
- 9.3 總結
- 10. Git 內部原理
- 10.1 底層命令和高層命令
- 10.2 Git 對象
- 10.3 Git 引用
- 10.4 包文件
- 10.5 引用規格
- 10.6 傳輸協議
- 10.7 維護與數據恢復
- 10.8 環境變量
- 10.9 總結
- A. 其它環境中的 Git
- A1.1 圖形界面
- A1.2 Visual Studio 中的 Git
- A1.3 Eclipse 中的 Git
- A1.4 Bash 中的 Git
- A1.5 Zsh 中的 Git
- A1.6 Powershell 中的 Git
- A1.7 總結
- B. 將 Git 嵌入你的應用
- A2.1 命令行 Git 方式
- A2.2 Libgit2
- A2.3 JGit
- C. Git 命令
- A3.1 設置與配置
- A3.2 獲取與創建項目
- A3.3 快照基礎
- A3.4 分支與合并
- A3.5 項目分享與更新
- A3.6 檢查與比較
- A3.7 調試
- A3.8 補丁
- A3.9 郵件
- A3.10 外部系統
- A3.11 管理
- A3.12 底層命令