手順

git log、diff、show、blame: Git でプロジェクトの履歴を読む方法

更新日: · Skillaria.Top

git log はコミットの一覧を表示し、作成者、日付、ファイル、メッセージでフィルターできます。git diff は作業ディレクトリ、インデックス、任意のコミット同士を比較します。git show は1つのコミットを丸ごと表示し、git blame は各行を最後に変更したコミットを示します。

4つのコマンドで、プロジェクトの履歴に関するほとんどの疑問に答えられます。git log は「何が起きたか」、git diff は「何がどう変わったか」、git show は「特定のコミットの中身は何か」、git blame は「この行を誰がいつ書いたか」に答えます。以下では、日常の開発で実際に使うフラグとともに、それぞれの実践的な使い方を紹介します。

git log: コミットの一覧

引数なしの git log は、現在のブランチのコミットを新しいものから古いものへ順に表示します。完全な SHA-1 ハッシュ、作成者、日付、メッセージが表示されます。出力はページャー(通常は less)で開きます。スペースで次のページ、/テキスト で検索、q で終了です。

commit 7be41d0c9a2e4f1b8d6c3e5a7f9b0c2d4e6f8a1b
Author: Anna Petrova <anna@example.com>
Date:   Mon Oct 5 14:22:10 2026 +0300

    feat: кэширование ответов API

ハッシュを全部コピーする必要はありません。Git は一意になる任意の接頭辞(4文字以上)を受け付けます。実際には7文字で十分なことが多いです。

コンパクトな表示: --oneline

git log --oneline -10
# 7be41d0 (HEAD -> main, origin/main) feat: кэширование ответов API
# 1c02e8f fix: таймаут запросов
# 9a4b3c2 refactor: вынес клиент в модуль

-10(または -n 10)はコミットの数を制限します。括弧の中には、HEAD の位置、ローカルとリモートのブランチ、タグが表示されます。

ブランチのグラフ: git log --graph

「git graph」と検索する人が求めているのは、通常このコマンドです。ブランチの分岐とマージを、ターミナルの中で図として表示します。

git log --oneline --graph --all
# * 3e1f0aa (feature/auth) feat: вход по токену
# | * 7be41d0 (HEAD -> main) feat: кэширование ответов API
# |/
# * 1c02e8f fix: таймаут запросов
# *   5d2c7b1 Merge branch 'feature/search'
# |\
# | * 8f3a9e0 feat: поиск
# |/
# * 9a4b3c2 refactor: вынес клиент в модуль

--all は現在のブランチだけでなく、すべてのブランチを表示します。エイリアスを作っておくと便利です: git config --global alias.lg "log --oneline --graph --all --decorate"。これで git lg と入力するだけで済みます。

独自の書式: --pretty=format

git log --pretty=format:"%h %ad %an %s" --date=short
# 7be41d0 2026-10-05 Anna Petrova feat: кэширование ответов API

主なプレースホルダーは次のとおりです。%h は短いハッシュ、%H は完全なハッシュ、%an は作成者名、%ae は作成者のメールアドレス、%ad は作成日、%ar は相対日付(「2 days ago」など)、%s はメッセージの件名です。

git log で履歴を絞り込む

作成者と日付で絞る

git log --author="Anna"
git log --since="2 weeks ago" --until="2026-10-01"
git log --since=yesterday --oneline

--author は正規表現を受け付け、名前とメールアドレスの両方を検索します。日付は自然な表現と ISO 形式のどちらでも指定できます。

メッセージの文字列で絞る

git log --grep="fix" -i --oneline

-i は大文字と小文字を区別しない検索にします。チームがメッセージにタスク番号を書いているなら、そのタスクに関するコミットをすぐに見つけられます。

ファイルやフォルダで絞る

git log --oneline -- src/api/client.py
git log --follow -p -- src/api/client.py

二重のハイフンは、パスとブランチ名を区切ります。--follow はリネームをまたいでファイルの履歴をたどります(1つのファイルに対してのみ動きます)。-p は各コミットのパッチを表示します。

コードの変化で探す: -S と -G

git log -S "retry_count" --oneline     # 文字列の出現回数が変わったコミット
git log -G "timeout\s*=" --oneline    # 差分の行が正規表現に一致するコミット

-S は、関数や変数が追加または削除されたコミットを見つけます。コードの一部がどこに消えたのかを知りたいときに欠かせません。

コミットの範囲を指定する

git log main..feature      # feature にあって main にないもの
git log origin/main..HEAD  # 自分のローカルにあって、まだ送信していないコミット
git log --no-merges        # マージコミットを除く
git log --stat             # 変更されたファイルと行数

git diff: 何がどう変わったか

git diff を理解するうえで最も大切なのは、どの2つの状態を比べているかです。「全部変えたのに diff が空なのはなぜ」という疑問は、ほとんどこの点の混乱から生まれます。

コマンド比較の対象
git diff作業ディレクトリとインデックス(未ステージの変更)
git diff --staged(--cached)インデックスと最新のコミット(次のコミットに入る内容)
git diff HEAD作業ディレクトリと最新のコミット(すべての変更)
git diff A B2つのコミット、ブランチ、またはタグ
git diff A...BA から分岐してからの B の変更

git add を実行すると、通常の git diff は空になります。変更がすでにインデックスに入っているからです。その場合は --staged を見てください。一度も追加されていない新規ファイルは、diff には一切表示されません。

diff の出力の読み方

diff --git a/config.py b/config.py
index 3b18e51..a1c4f02 100644
--- a/config.py
+++ b/config.py
@@ -10,7 +10,7 @@ DEFAULTS = {
     "host": "localhost",
-    "timeout": 5,
+    "timeout": 30,
     "retries": 3,

- で始まる行は削除、+ で始まる行は追加、それ以外は前後の文脈です。見出し @@ -10,7 +10,7 @@ は、このかたまりが旧版と新版でそれぞれ10行目と10行目から始まり、7行ずつを占めることを意味します。

git diff の便利なオプション

git diff --stat main feature      # ファイルごとの概要
git diff --name-only HEAD~3       # 変更されたファイル名だけ
git diff --word-diff               # 単語単位の差分。文章の編集に便利
git diff -w                        # 空白の変更を無視
git diff main feature -- src/      # フォルダに限定する

コミットの前には git diff --staged を確認する習慣をつけましょう。デバッグ用の print や、うっかり追加したファイルに気づく最後の機会です。

git show: 1つのコミットを丸ごと表示する

git show は、コミットのメタデータと、親との差分を表示します。引数を省略すると、最新のコミットを表示します。

git show 7be41d0
git show HEAD~2 --stat           # パッチなし、概要だけ
git show v1.2.0                  # タグ: 注釈とコミット
git show main:src/config.py      # コミット時点のファイルの内容

最後の <リビジョン>:<パス> の形式は特に便利です。チェックアウトせずに、古いバージョンのファイルを見られます。出力をファイルにリダイレクトすれば、checkout なしで削除されたファイルの内容を復元できます。

git blame: この行を書いたのは誰か

git blame ファイル は、各行について、最後に変更したコミット、作成者、日時を表示します。名前は犯人探しのように聞こえますが、実際には文脈を探すための道具です。コミットを見つけ、メッセージを読み、なぜそのように書かれたのかを理解するために使います。

git blame -L 40,60 src/api/client.py
# 1c02e8f3 (Anna Petrova 2026-09-28 11:04:51 +0300 41)     timeout = settings.timeout
# 9a4b3c2e (Ivan Smirnov 2026-09-14 18:30:02 +0300 42)     session = build_session()
  • -L 40,60: 行の範囲だけを表示します。-L :関数名 も使えます。
  • -w: 空白の変更を無視します。整形だけのコミットに当たらないようにします。
  • -C: 他のファイルから移動してきた行も追跡します。
  • --ignore-rev <ハッシュ> や .git-blame-ignore-revs ファイルを使うと、自動整形のような大量の変更を飛ばせます。

典型的な調査の流れは、git blame でコミットを見つけ、git show でそのコミット全体を見て、git log でそのファイルの前後の変更を確認する、というものです。

過去を指し示す: HEAD~ と HEAD^

コミットはハッシュだけでなく、別の方法でも指定できます。HEAD~1 は現在のコミットの親、HEAD~3 は3つ前のコミットです。HEAD^2 はマージコミットの2番目の親を指します。ブランチ、タグ、リモートブランチの名前も使えます(例: origin/main~2)。古いコミットでプロジェクト全体を見るには git switch --detach <ハッシュ> を、元に戻るには git switch - を使います。

良い履歴と悪い履歴

これらのコマンドが役立つかどうかは、履歴がどれだけ意味を持つかにかかっています。「fix」「wip」「もう少し修正」のようなメッセージばかりでは、git log --grep も git blame も役に立ちません。良いコミットは、1つの論理的な変更を持ち、何をなぜ変えたかを件名で説明しています。例: fix: API のタイムアウトを 30 秒に延長(ゲートウェイが遅いため)。半年後、このようなコミットを blame が見つけてくれれば、1時間の調査が節約できます。

実践: 履歴からバグを調べる

リリース後、API へのリクエストがタイムアウトするようになったとします。コマンドを組み合わせると、数分で原因にたどり着けます。

  1. リリースに何が入ったかを確認: git log v1.4.0..v1.5.0 --oneline。件数は少ないですが、件名だけでは原因が分かりにくいです。
  2. ファイルで絞り込む: git log v1.4.0..v1.5.0 --oneline -- src/api/。候補は2つのコミットに絞られます。
  3. コードで探す: git log -S "timeout" --oneline -- src/api/ で、タイムアウトの値が変わったコミットを見つけます。
  4. コミット全体を見る: git show 1c02e8f。差分では、タイムアウトが 30 秒から 5 秒に減らされていて、メッセージには「UI の応答を速くするため」と書かれています。
  5. この行を書いた人を確認: git blame -L :build_session src/api/client.py。

ここからは、設計の問題として判断します。値を元に戻すか、タイムアウトを設定に切り出すか、git revert でコミットを取り消します。コミットが何百もあって目視で探せない場合は、git bisect が役立ちます。これは二分探索で、数ステップのうちに、動作を壊したコミットを特定します。

作業を楽にする設定

git config --global log.date iso            # log の日付を ISO 形式に
git config --global diff.colorMoved zebra   # diff で移動した行を色分け
git config --global core.pager "less -FRX"  # 短い出力ではページャーを開かない

出力をスクリプトで処理する場合は、色とページャーを無効にします: git --no-pager log --format="%H %s" --no-color。機械的に処理するなら、完全なハッシュ %H を使ってください。短い接頭辞は、大きなリポジトリでは時間とともに曖昧になることがあります。

まとめ

--oneline、--graph、--author、-S、パス指定を付けた git log は「何が起きたか」に答えます。git diff は作業ディレクトリ、インデックス、コミットを比較し、デフォルトで何を比べているかを覚えておくことが大切です。git show は1つのコミットや古いファイルの内容を示し、git blame はコードの行から、それを生んだ判断までたどらせてくれます。履歴の読み方とコミット間の移動は、Gitコースで実践的に扱っています。

よくある質問

git log から抜けるにはどうすればよいですか?

q を押してください。出力はページャーの less で開かれています。ページャーを使わずに表示するには git --no-pager log を使うか、-n で件数を少なくします。

削除されたファイルの履歴を見るにはどうすればよいですか?

git log --oneline -- パス/ファイル(二重のハイフン付き)を実行します。削除前の内容は git show ハッシュ^:パス/ファイル で見られます。

ローカルのブランチとリモートのブランチを比べるにはどうすればよいですか?

先に git fetch を実行し、その後 git diff origin/main、または git log origin/main..HEAD で、まだ送信していないコミットを確認します。

履歴をグラフで見る方法はありますか?

Git に付属する gitk があります。また、VS Code、JetBrains の IDE、GitHub や GitLab の Web インターフェースにも、履歴のグラフが組み込まれています。

git diff が何も表示しないのはなぜですか?

変更がすでに git add でインデックスに入っている可能性が高いです。git diff --staged を確認してください。Git に追加されていない新規ファイルは、git diff には表示されません。

動画でこのテーマを学ぶ

このテーマはコース「Git:初心者から自信を持って使える開発者へ」で実践とともに詳しく解説しています。

コースへ