バージョン管理システムの目的はコードへの変更内容を記録することです。これにより、プロジェクト履歴に戻って誰が何を行ったかを確認したり、バグが生じた場所を見つけたり、問題のある変更を元に戻したりすることができます。しかし、履歴をナビゲートする方法を知らなければ、この履歴のすべてを利用できるようにしても役に立ちません。そこで、git log コマンドの出番です。

みなさんはコミットを表示するための基本的な git log コマンドを既に知っています。しかし、多くの様々なパラメーターを git log に渡すことでこの出力を変更することが可能です。

git log の高度な機能は次の2つのカテゴリに分類できます。各コミットの表示方法の形式設定と、出力に含めるコミットのフィルタリングです。これら2つのスキルを組み合わせると、プロジェクトに戻り、必要となる可能性のある情報を検索できます。

ログ出力のフォーマット

最初に、この記事では git log の出力の表示形式を設定できる多くの方法について説明します。これらのほとんどはフラグ形式で、ユーザーはほとんどの情報を git log からリクエストできます。

既定の git log 形式にしない場合は、git config のエイリアス機能を使用して、以下で説明している表示形式設定オプションのショートカットを作成できます。エイリアスの設定方法については、「git config コマンド」を参照してください。

Oneline

--oneline フラグは、各コミットを単一行に凝縮します。既定では、コミット ID とコミットメッセージの最初の行のみを表示します。一般的な git log --oneline 出力は次のように表示されます。

0e25143 Merge branch 'feature'
ad8621a Fix a bug in the feature
16b36c6 Add a new feature
23ad9ad Add the initial code base

これは、プロジェクトのハイレベルの概要を取得するには非常に便利です。

Decorate

各コミットが関連付けられているブランチまたはタグがわかると何倍も便利です。--decorate フラグを使用すると git log で各コミットをポイントする参照 (ブランチやタグなど) がすべて表示されます。

これは、他の設定オプションと組み合わせることが可能です。たとえば、git log —oneline —decorate を実行すると、コミット履歴の表示形式は次のようになります。

0e25143 (HEAD, main) Merge branch 'feature'
ad8621a (feature) Fix a bug in the feature
16b36c6 Add a new feature
23ad9ad (tag: v0.9) Add the initial code base

これにより先頭のコミットもチェックアウトされ (HEAD によって示されています)、これが main ブランチの先端でもあることがわかります。2 番目のコミットにはそれをポイントしている feature と呼ばれる別のブランチがあり、最後に 4 番目のコミットが v0.9 とタグ付けされています。

ブランチ、タグ、HEAD、およびコミット履歴は、ご使用の Git リポジトリに含まれているほぼすべての情報です。このため、リポジトリの論理的構造のより完全なビューを取得できます。

Diff

git log コマンドには各コミットの diff を表示するための多くのオプションがあります。最もよく使用されるオプションのうちの2つは、--stat-p です。

--stat オプションは、各コミットによって変更された各ファイルの挿入および削除の数を表示します (行の修正は、1 insertion (挿入) および 1 deletion (削除) のように表現されます)。これは各コミットによって生じた変更の簡単な概要が必要な場合に便利です。たとえば、次のコミットは hello.py ファイルに 67 行追加し、38 行削除しました。

commit f2a238924e89ca1d4947662928218a06d39068c3
Author: John <john@example.com>
Date:   Fri Jun 25 17:30:28 2014 -0500

    Add a new feature

 hello.py | 105 ++++++++++++++++++++++++-----------------
 1 file changed, 67 insertion(+), 38 deletions(-)

ファイル名の横にある +- 符号の量は、コミットによって変更された各ファイルに対する変更の相対数を示しています。これは、各コミットにより変更された場所を見つける手がかりになります。これにより、各コミットの変更がどこで見つかるかがわかります。

各コミットによって生じた実際の変更を見る必要がある場合、-p オプションを git log に渡します。これにより、そのコミットを表す全パッチが出力されます。

commit 16b36c697eb2d24302f89aa22d9170dfe609855b
Author: Mary <mary@example.com>
Date:   Fri Jun 25 17:31:57 2014 -0500

    Fix a bug in the feature

diff --git a/hello.py b/hello.py
index 18ca709..c673b40 100644
--- a/hello.py
+++ b/hello.py
@@ -13,14 +13,14 @@ B
-print("Hello, World!")
+print("Hello, Git!")

多くの変更を含むコミットの場合、結果の出力は非常に長く、扱いにくくなりがちです。だいたいにおいて、完全なパッチを表示している場合、特定の変更を検索しています。このため、pickaxe オプションを使用する必要があります。

Shortlog

git shortlog コマンドは git log の特別なバージョンで、リリースのお知らせを作成することを目的としています。作成者別に各コミットを分類し、各コミットメッセージの最初の行を表示します。これは、誰がどんな作業をしているかについて確認する簡単な方法です。

たとえば、2 人の開発者がプロジェクトに 5 コミット発行した場合、git shortlog 出力は次のように表示されます。

Mary (2):
      Fix a bug in the feature
      Fix a serious security hole in our framework

John (3):
      Add the initial code base
      Add a new feature
      Merge branch 'feature'

既定では、git shortlog は作成者名で出力を分類しますが、-n オプションを渡して作成者ごとのコミットの数で分類することも可能です。

Graph

--graph オプションは、コミット履歴のブランチ構造を表す ASCII グラフを描画します。これは一般的に、--oneline および --decorate コマンドと組み合わせて使用され、どのコミットがどのブランチに属しているかを確認することが容易になります。

git log --graph --oneline --decorate

ブランチが2つだけの単純なリポジトリの場合、これは次のようになります。

*   0e25143 (HEAD, main) Merge branch 'feature'
|\  
| * 16b36c6 Fix a bug in the new feature
| * 23ad9ad Start a new feature
* | ad8621a Fix a critical security issue
|/  
* 400e4b7 Fix typos in the documentation
* 160e224 Add the initial code base

アスタリスクはコミットが存在したブランチを示すため、上記のグラフから、23ad9ad および 16b36c6 コミットはトピック ブランチにあり、残りのコミットは main ブランチにあることがわかります。

単純なリポジトリの場合、これは役立つオプションですが、多くのブランチがあるプロジェクトでは、より完全な構造を視覚化できる gitkSourcetree のようなツールを使用する方が便利でしょう。

カスタム形式設定

他のすべての git log 表示形式を設定するニーズに対しては、--pretty=format:"" オプションを使用できます。これにより、printf 型のプレースホルダーを使用して各コミットを必要なだけ表示できます。

たとえば、次のコマンドで %cn%h および %cd 文字はそれぞれ、コミッター名、短縮されたコミットハッシュ、およびコミッター日付に置き換えられます。

git log --pretty=format:"%cn committed %h on %cd"

これにより、各コミットについて、次の形式で返されます。

John committed 400e4b7 on Fri Jun 24 12:30:04 2014 -0500 John committed 89ab2cf on Thu Jun 23 17:09:42 2014 -0500 Mary committed 180e223 on Wed Jun 22 17:21:19 2014 -0500 John committed f12ca28 on Wed Jun 22 13:50:31 2014 -0500

プレースホルダーの完全なリストは git log マニュアル ページの Pretty フォーマット セクションにあります。

関心のある情報のみを表示することに加えて、--pretty=format:"" オプションは git log 出力を別のコマンドにパイピングしようとする場合に特に役立ちます。

コミット履歴にフィルターをかける

git log について、各コミットの表示方法の形式設定を習得しただけでは不十分です。残りの半分は、コミット履歴をナビゲートする方法を理解することです。この記事の残りの部分では、git log を使用してプロジェクト履歴で特定のコミットを見つけ出す高度な方法をいくつか紹介します。これらはすべて、上記で説明した表示形式設定オプションのいずれとも組み合わせることが可能です。

量によるフィルタリング

git log の最も基本的なフィルタリング オプションは、表示されるコミット数を限定することです。最近のいくつかのコミットにのみ関心がある場合、フィルタリングすることでページにすべてのコミットを表示する手間が省けます。

git log の出力は - オプションを指定することで制限できます。たとえば、次のコマンドは3つの最新のコミットのみを表示します。

git log -3

日付によるフィルタリング

特定の期間のコミットを探す場合は、--after または --before フラグを使用して日付によってコミットをフィルタリングします。これらは両方ともパラメーターとして多様な日付形式を受け入れます。たとえば、次のコマンドは、2014 年 7 月 1 日以降に作成されたコミットのみを表示します。

git log --after="2014-7-1"

"1 week ago" (1 週間前) および "yesterday" (昨日) のような相対参照で渡すこともできます。

 git log --after="yesterday"

2つの日付の間で作成されたコミットを検索するには、--before--after の両方の日付を指定できます。たとえば、2014 年 7 月 1 日と 2014 年 7 月 4 日の間に追加されたすべてのコミットを表示するには、次のようにします。

git log --after="2014-7-1" --before="2014-7-4"

--since および --until フラグはそれぞれ、--after および --before と同義です。

作成者によるフィルタリング

特定のユーザーが作成したコミットのみを検索する場合は、 --author フラグを使用します。これは正規表現を受け入れ、そのパターンに一致する作成者のすべてのコミットを返します。検索する相手が正確にわかっている場合は、正規表現の代わりに従来のプレーンテキストを使用できます。

git log --author="John"

これは John という名前を含むコミットの作成者をすべて表示します。作成者名は完全一致である必要はありません。単に、指定された語句を含んでいる 必要があるだけです。

正規表現を使用して、さらに複雑な検索を作成することもできます。たとえば、次のコマンドは、コミットを Mary または John のいずれかで検索します。

git log --author="John\|Mary"

作成者のメールも作成者の名前に付随するため、このオプションを使用してメールで検索することも可能です。

ワークフローでコミッターと作成者を分離している場合、--committer フラグが同じように動作します。

メッセージによるフィルタリング

コミットをコミットメッセージによりフィルタリングするには、--grep フラグを使用します。これは、上記で説明した --author フラグと同様に動作しますが、作成者ではなく、コミットメッセージに一致するものを照合します。

たとえば、チームが関連する課題番号を各コミットメッセージに取り込む場合、次のようにすると、その課題に関係するすべてのコミットを取得できます。

git log --grep="JRA-224:"

-i パラメーターを git log に渡して、パターン マッチングの間は大文字/小文字の区別を無視するように設定することもできます。

ファイルによるフィルタリング

特定のファイルに生じた変更のみを知りたい場合もよくあります。ファイルに関連する履歴を表示するために必要なことは、ファイルパスを渡すだけです。たとえば、次のコマンドは、foo.py または bar.py ファイルのいずれかに影響を与えたすべてのコミットを返します。

git log -- foo.py bar.py

-- パラメーターは、後続の引数がブランチ名ではなく、ファイルパスであることを git log に伝えるために使用されます。ブランチと混同される可能性がまったくない場合は、-- を省略できます。

コンテンツによるフィルタリング

ソースコードの特定の行を追加または削除するコミットを検索することも可能です。これは pickaxe と呼ばれ、形式は -S"" です。たとえば、文字列 Hello, World! がプロジェクト内のいずれかのファイルにいつ追加されたのか知りたい場合、次のコマンドを使用します。

git log -S"Hello, World!"

文字列ではなく、正規表現を使用して検索したい場合は、 -G"" フラグを代わりに使用できます。

これは非常に強力なデバッグツールで、特定のコード行に影響を与えるすべてのコミットの場所を見つけることができます。コード行が別のファイルにコピーまたは移動された場合でも、その場所を示すことが可能です。

範囲によるフィルタリング

コミットの範囲を git log に渡すと、その範囲に含まれるコミットのみを表示できます。この範囲は、次の形式で指定されます。ここで、 および はコミット参照です。

git log ..

このコマンドは、パラメーターとしてブランチ参照を使用する場合に特に役立ちます。2つのブランチ間の相違を示す単純な方法です。次のコマンドを考えます。

 git log main..feature

main..feature 範囲には、feature ブランチにはあり、main ブランチにはないコミットがすべて含まれています。つまり、これは featuremaster からフォークした後、作業が進行したことを示します。これは次のように可視化できます。

範囲を使用して履歴でフォークを検出

範囲 (feature.. main) の順序を切り替えると、main にはあるが feature にはないすべてのコミットを取得します。git log が両方のバージョンのコミットを出力する場合、これは履歴が分岐したことを示しています。

マージコミットのフィルタリング

既定では、git log の出力にはマージコミットが含まれます。しかし、チームに「常にマージ」ポリシーがあると (つまり、トピックブランチを上流ブランチにリベースするのではなく、上流の変更をトピックブランチにマージする)、多くの無関係なマージコミットがプロジェクト履歴に残ることになります。

git log がこれらのマージコミットを表示しないようにするには、--no-merges フラグを渡します。

git log --no-merges

反対に、マージコミットにのみ関心がある場合、--merges フラグを使用します。

git log --merges

これにより、2つ以上の親を持つすべてのコミットが返されます。

概要

これで皆さんは git log の高度なパラメーターを快適に使いこなして出力形式の設定や表示したいコミットの選択を行えるようになりました。したがって、プロジェクト履歴から必要なものを正確に取り出すことができます。

これらの新しいスキルは Git ツールキットの重要な部分ですが、git log は多くの場合、他の Git コマンドと共に使用されることを覚えておいてください。探しているコミットが見つかったら、コミット履歴を操作するためにそれを git checkoutgit revert、または他のツールに渡すのが一般的です。それでは、今後も Git の高度な機能について学習を欠かさないようにしましょう。

git log を学ぶ準備はできていますか?

この対話式チュートリアルを利用しましょう。

今すぐ始める