コードを読んでいて「この条件分岐は何のために入っているのだろう」と手が止まることがあります。コメントもなく、消していいのかどうかも分からない。こういうときに頼りになるのが、その行が書かれた経緯です。
git blame は、ファイルの1行ごとに「最後に変更したコミット」を表示するコマンドです。誰がいつ、どのコミットでその行を書いたのかが分かるので、そこからコミットメッセージや Pull Request をたどれば、意図までさかのぼれます。
この記事では、出力の読み方から、範囲を絞る指定、整形だけのコミットを無視する方法、そして削除された行の追いかけ方までを解説します。
目次
基本の使い方と出力の読み方
ファイル名を渡すだけで実行できます。
$ git blame src/search.js
28f9e36c (Taro Yamada 2025-06-11 14:03:51 +0900 1) export function search(query) {
28f9e36c (Taro Yamada 2025-06-11 14:03:51 +0900 2) const keyword = query.trim();
4a71d20f (Hanako Sato 2025-08-02 09:47:12 +0900 3) // 空文字のときは全件返す
4a71d20f (Hanako Sato 2025-08-02 09:47:12 +0900 4) if (keyword === '') {
4a71d20f (Hanako Sato 2025-08-02 09:47:12 +0900 5) return getAll();
28f9e36c (Taro Yamada 2025-06-11 14:03:51 +0900 6) }
左から順に、コミットハッシュ・作者・変更日時・行番号・その行の内容が並びます。この例では、3行目から5行目だけが別のコミット(4a71d20f)で追加されたことが分かります。あとから条件分岐が足されたわけです。
気になるコミットが見つかったら、そのハッシュを git show に渡します。コミットメッセージと、そのとき何を変更したのかを一度に確認できます。
$ git show 4a71d20f
commit 4a71d20f8c3b1e0a9d5f2c7b4e8a6d3f1c0b9e8a
Author: Hanako Sato <hanako@example.com>
Date: Sat Aug 2 09:47:12 2025 +0900
検索欄が空のときに0件になる不具合を修正
(以下、差分)
「不具合の修正で入った分岐だった」と分かれば、安易に消してはいけないことが判断できます。これが git blame の一番の使いどころです。
調べる範囲を絞る
数百行のファイルをすべて表示しても目が滑ります。気になっている箇所が分かっているなら、-L で行の範囲を指定します。
# 40行目から60行目まで
$ git blame -L 40,60 src/search.js
# 40行目から20行ぶん
$ git blame -L 40,+20 src/search.js
# 関数名で指定する(対応している言語なら)
$ git blame -L :search:src/search.js
よく使うオプションをまとめておきます。
| オプション | 効果 |
|---|---|
-L <開始>,<終了> | 指定した行範囲だけを表示する |
-w | 空白だけの変更を無視する |
-M | 同じファイル内で行が移動した場合、移動前のコミットをたどる |
-C | 他のファイルからコピー・移動してきた行もたどる |
-e | 作者名のかわりにメールアドレスを表示する |
--date=short | 日時を 2025-08-02 の形式で短く表示する |
<コミット> -- | 指定したコミット時点の状態で blame する |
最後の指定は少し分かりにくいので補足します。git blame 9f3c1ab -- src/search.js のように書くと、「そのコミット時点でのファイル」を対象に blame できます。現在のコードではなく、過去のある時点の状態を調べたいときに使います。
整形だけのコミットを無視する
git blame を実行したら、ほとんどの行が「Prettier を導入した」という1つのコミットになっていた。こういう経験は珍しくありません。フォーマッタによる一括整形や、インデントの変更が入ると、本来の作者の情報が埋もれてしまいます。
まず試すのが -w です。空白やインデントだけの変更を無視して、意味のある変更をたどってくれます。
# 空白の変更を無視し、移動・コピーもたどる
$ git blame -w -M -C src/search.js
それでも足りない場合は、特定のコミットを名指しで除外できます。--ignore-rev に指定したコミットは blame の対象から外され、その1つ前の変更が表示されます。
# 一括整形のコミットを無視する
$ git blame --ignore-rev 7c2e8b1 src/search.js
毎回オプションを付けるのは面倒なので、チームで共有するならファイルにまとめます。除外したいコミットハッシュを1行ずつ書いたファイルを用意し、Git の設定でそれを指定します。
# Prettier を導入して全ファイルを整形
7c2e8b1a4f6d9e0c3b5a8d2f1e7c4b9a6d3f0e8c
# インデントをタブからスペースに統一
2b9d5f8e1c4a7b0d3e6f9c2a5b8d1e4f7a0c3b6d
# このリポジトリで常に適用する
$ git config blame.ignoreRevsFile .git-blame-ignore-revs
このファイルはリポジトリにコミットしておけます。GitHub も .git-blame-ignore-revs を認識するので、ウェブ上の blame 表示にも反映されます。大規模な整形を行ったら、そのコミットをここに追記するのを習慣にしておくとよいでしょう。
行の履歴をさらにさかのぼる
git blame が教えてくれるのは「最後に変更したコミット」だけです。その行がそれ以前にどう書かれていたかを知りたいときは、git log -L を使います。指定した行範囲の変更履歴を、差分付きで古い順にさかのぼれます。
# 3行目から5行目の変更履歴をすべて表示する
$ git log -L 3,5:src/search.js
# 関数単位でもたどれる
$ git log -L :search:src/search.js
「この行は何度も書き換えられているのか、一度書かれたきりなのか」が分かるので、blame より踏み込んだ調査ができます。
知りたい情報が出てこないとき
削除された行は blame に出てこない
git blame は現在存在する行しか表示しません。「以前あった処理がいつ消えたのか」を調べるには使えません。この場合は git log -S が有効です。指定した文字列の出現回数が変わったコミットだけを抽出してくれます。
# この関数名が追加・削除されたコミットを探す
$ git log -S "legacySearch" --oneline
9f3c1ab 旧検索処理を削除
28f9e36 検索機能を追加
ファイルを移動したら履歴が途切れた
ディレクトリ構成を変えたあとの blame では、移動のコミットが全行に表示されることがあります。-C を付けると、他のファイルから移動・コピーされてきた行を追跡してくれます。効き目が弱いときは -C -C のように重ねると、検出の範囲が広がります。
コミットが「Not Committed Yet」になる
作者名が Not Committed Yet と表示される行は、まだコミットしていない手元の変更です。自分が編集中の行なので、履歴を調べたい場合はいったん変更を退避するか、コミット済みの状態を指定して blame してください。
マージコミットばかりが表示される
ブランチの取り込み方によっては、実際の変更者ではなくマージした人が表示されることがあります。その場合は表示されたコミットを git show で開き、そこから元のコミットをたどってください。GitHub を使っているなら、blame 画面から Pull Request に直接ジャンプできるので、議論の経緯まで一度に確認できます。
まとめ
git blame <ファイル> は、行ごとに最後の変更コミット・作者・日時を表示するコマンドです。気になる行のコミットハッシュを git show に渡せば、その変更が入った理由まで確認できます。
実際に使うときは -L で範囲を絞り、整形の影響を受けるなら -w -M -C を付ける、というのが基本の形です。一括整形のコミットがあるリポジトリでは、.git-blame-ignore-revs を用意しておくと、以後の調査がずっと楽になります。
名前のとおり「犯人探し」に使うコマンドではありません。コードの意図を読み解くための道具として使えば、知らないコードベースを触るときの心強い味方になります。