Git
Chapters ▾ 2nd Edition

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

    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 は、直近の 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

このオプションは、先ほどと同じ情報を表示するとともに、各エントリの直後にその 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

    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 オプションは、各コミットを一行で出力します。 これは、大量のコミットを見る場合に便利です。 さらに shortfull そして 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

git log --pretty=format 用の便利なオプション は、format で使用できる便利なオプションをまとめたものです。

表 1. git log --pretty=format 用の便利なオプション
オプション 出力される内容

%H

コミットのハッシュ

%h

コミットのハッシュ (短縮版)

%T

ツリーのハッシュ

%t

ツリーのハッシュ (短縮版)

%P

親のハッシュ

%p

親のハッシュ (短縮版)

%an

Author の名前

%ae

Author のメールアドレス

%ad

Author の日付 (--date= オプションに従った形式)

%ar

Author の相対日付

%cn

Committer の名前

%ce

Committer のメールアドレス

%cd

Committer の日付

%cr

Committer の相対日付

%s

件名

authorcommitter は何が違うのか気になる方もいるでしょう。 authorとはその作業をもともと行った人、committerとはその作業を適用した人のことを指します。 あなたがとあるプロジェクトにパッチを送り、コアメンバーのだれかがそのパッチを適用したとしましょう。 この場合、両方がクレジットされます (あなたがauthor、コアメンバーがcommitterです)。 この区別については[ch05-distributed-git]でもう少し詳しく説明します。

oneline`オプションおよび`format`オプションは、`log のもうひとつのオプションである --graph と組み合わせるとさらに便利です。 このオプションは、ちょっといい感じのアスキーグラフでブランチやマージの歴史を表示します。

$ 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 の出力フォーマット指定のほんの一部でしかありません。 まだまだオプションはあります。 `git log`のよく使われるオプション に、今まで取り上げたオプションやそれ以外によく使われるオプション、 そしてそれぞれが`log`の出力をどのように変えるのかをまとめました。

表 2. `git log`のよく使われるオプション
オプション 説明

-p

各コミットのパッチを表示する

--stat

各コミットで変更されたファイルの統計情報を表示する

--shortstat

--stat コマンドのうち、変更/追加/削除 の行だけを表示する

--name-only

コミット情報の後に変更されたファイルの一覧を表示する

--name-status

変更されたファイルと 追加/修正/削除 情報を表示する

--abbrev-commit

SHA-1 チェックサムの全体 (40文字) ではなく最初の数文字のみを表示する

--relative-date

完全な日付フォーマットではなく、相対フォーマット (“2 weeks ago” など) で日付を表示する

--graph

ブランチやマージの歴史を、ログ出力とともにアスキーグラフで表示する

--pretty

コミットを別のフォーマットで表示する。オプションとして oneline, short, full, fuller そして format (独自フォーマットを設定する) を指定可能

ログ出力の制限

出力のフォーマット用オプションだけでなく、 git log にはログの制限用の便利なオプションもあります。 コミットの一部だけを表示するようなオプションのことです。 既にひとつだけ紹介していますね。 -2 オプション、これは直近のふたつのコミットだけを表示するものです。 実は -<n>n には任意の整数値を指定することができ、直近の n 件のコミットだけを表示させることができます。 ただ、実際のところはこれを使うことはあまりないでしょう。 というのも、Git はデフォルトですべての出力をページャにパイプするので、 ログを一度に 1 ページだけ見ることになるからです。

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

$ git log --since=2.weeks

このコマンドはさまざまな書式で動作します。特定の日を指定する ("2008-01-15") こともできますし、 相対日付を`"2 years 1 day 3 minutes ago"`のように指定することも可能です。

コミット一覧から検索条件にマッチするものだけを取り出すこともできます。 --author オプションは特定のauthorのみを抜き出し、 --grep オプションはコミットメッセージの中のキーワードを検索します (author と grep を両方指定する場合は、`--all-match`オプションも一緒に使ってください。 そうしないと、どちらか一方にだけマッチするものも対象になってしまいます)。

もうひとつ、`-S`オプションというとても便利なフィルタがあります。 このオプションは任意の文字列を引数にでき、その文字列が追加・削除されたコミットのみを抜き出してくれます。 仮に、とある関数の呼び出しをコードに追加・削除したコミットのなかから、最新のものが欲しいとしましょう。こうすれば探すことができます。

$ git log -Sfunction_name

最後に紹介する git log のフィルタリング用オプションは、パスです。 ディレクトリ名あるいはファイル名を指定すると、それを変更したコミットのみが対象となります。 このオプションは常に最後に指定し、一般にダブルダッシュ (--) の後に記述します。 このダブルダッシュが他のオプションとパスの区切りとなります。

`git log`の出力を制限するためのオプション に、これらのオプションとその他の一般的なオプションをまとめました。

表 3. `git log`の出力を制限するためのオプション
オプション 説明

-(n)

直近の n 件のコミットのみを表示する

--since, --after

指定した日付より後に作成されたコミットのみに制限する

--until, --before

指定した日付より前に作成されたコミットのみに制限する

--author

エントリが指定した文字列にマッチするコミットのみを表示する

--committer

エントリが指定した文字列にマッチするコミットのみを表示する

--grep

指定した文字列がコミットメッセージに含まれているコミットのみを表示する

-S

指定した文字列をコードに追加・削除したコミットのみを表示する

一つ例を挙げておきましょう。Git ソースツリーのテストファイルに対する変更があったコミットのうち、Junio Hamano がコミットしたものでかつ2008年10月にマージされたものを知りたければ、次のように指定します。

$ 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

約 40,000 件におよぶ Git ソースコードのコミットの歴史の中で、このコマンドの条件にマッチするのは 6 件となります。

scroll-to-top