チャプター ▾ 第2版

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があります。また、-2を使用して最後の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

このオプションは、各エントリの直後に差分を伴って同じ情報を表示します。これは、コードレビューや、共同作業者が追加した一連のコミット中に何が起こったのかを素早く閲覧するのに非常に役立ちます。また、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値は各コミットを1行で出力し、多くのコミットを閲覧する場合に便利です。さらに、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=optionに準拠した形式)

%ar

作者日付 (相対形式)

%cn

コミッター名

%ce

コミッターのメールアドレス

%cd

コミッター日付

%cr

コミッター日付 (相対形式)

%s

件名

作者コミッターの違いは何だろう、と疑問に思うかもしれません。作者は元々その作業を書いた人であり、コミッターは最後にその作業を適用した人です。つまり、プロジェクトにパッチを送り、コアメンバーの一人がそのパッチを適用した場合、あなた(作者として)とコアメンバー(コミッターとして)の両方に貢献があったことになります。この違いについては、分散Gitで詳しく説明します。

onelineformatオプション値は、--graphと呼ばれる別のlogオプションと組み合わせると特に便利です。このオプションは、ブランチとマージの履歴を示す小さなアスキーグラフを追加します。

$ 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

40文字すべてのSHA-1チェックサムではなく、最初の数文字のみを表示します。

--relative-date

完全な日付形式ではなく、相対形式(例: 「2 weeks ago」)で日付を表示します。

--graph

ログ出力の横に、ブランチとマージ履歴のアスキーグラフを表示します。

--pretty

コミットを代替形式で表示します。オプション値には、onelineshortfullfuller、およびformat(独自の形式を指定)があります。

--oneline

--pretty=oneline --abbrev-commitをまとめて使用する省略形です。

ログ出力の制限

出力整形オプションに加えて、git logはいくつかの便利な制限オプションも受け付けます。つまり、コミットのサブセットのみを表示するオプションです。既にそのようなオプションの1つ、最後の2つのコミットのみを表示する-2オプションを見ました。実際には、-<n>nは任意の整数)で最後のn個のコミットを表示できます。実際には、Gitはデフォルトですべての出力をページャーを通して表示するため、一度に1ページしかログ出力を見ないため、このオプションを頻繁に使用することはないでしょう。

しかし、--since--untilのような時間制限オプションは非常に便利です。たとえば、このコマンドは過去2週間に作成されたコミットのリストを取得します。

$ 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

文字列に一致するコードを追加または削除するコミットのみを表示します。

たとえば、Gitのソースコード履歴でテストファイルを変更したコミットのうち、2008年10月に浜野純男(Junio Hamano)によってコミットされ、かつマージコミットではないものを見たい場合、次のように実行できます。

$ 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