Claude Codeでgit blameから整形コミットを外す — .git-blame-ignore-revs
一括整形コミットを探して.git-blame-ignore-revsに登録し、git configとGitHubのblameビューで効かせる手順です。Claude Codeに候補を洗わせる指示と、ハッシュの書き方の落とし穴も扱います。
.git-blame-ignore-revsは、git blameに「この整形コミットは無かったことにして」と伝えるためのファイルです。リポジトリのルートに置いてコミットすると、GitHubのblameビューは自動で読みます。手元のgit blameにはgit config blame.ignoreRevsFile .git-blame-ignore-revsを1回実行すれば効きます。
Claude Codeに任せるのは、ファイルに入れる整形コミットを履歴から洗い出す作業と、書いたハッシュが全部実在するかの検査です。ハッシュを推測で書かせないことが、この手順の要になります。
整形コミットがblameを埋めるとき何が起きるか
Prettierやblackを全ファイルにかけた1コミットがあると、変わった行すべての「最後に触ったコミット」がそのコミットになります。経緯を知りたい行をgit blameしても、返ってくるのは「style: format with prettier」だけです。
空のリポジトリで再現すると、次のように見えます。2行の関数を書いてコミットし、addだけを整形したコミットを重ねました(Git 2.50.1で実行、ハッシュは短縮)。
git blame util.js442c5587 (dev 2026-10-28 18:47:25 +0900 1) function add(a, b) {
442c5587 (dev 2026-10-28 18:47:25 +0900 2) return a + b;
442c5587 (dev 2026-10-28 18:47:25 +0900 3) }
^2cbba79 (dev 2026-10-28 18:47:25 +0900 4) function sub(a,b){return a-b}整形された1〜3行目は442c5587を指し、触られていない4行目だけが最初のコミットに残っています。実際のリポジトリでは、整形された行が数万行になります。-wで空白の差を無視する方法はgit履歴から経緯を調べる記事にありますが、セミコロンの追加や改行位置の変更は空白の差ではないので、-wでは戻りません。そこで、整形コミットそのものを外す仕組みが要ります。
手順の全体像
導入の流れ
- 1
整形コミットを洗い出す
履歴から一括整形らしいコミットを探し、中身を確かめてから候補にします。
- 2
ルートにファイルを作る
40桁のハッシュを1行に1つ書き、
#でコメントを添えます。 - 3
手元のgitに設定する
blame.ignoreRevsFileでファイルを指定します。 - 4
GitHubで確認する
ファイルをコミットして、blameビューのバナーを見ます。
Claude Codeに整形コミットを洗い出させる
整形コミットは、コミットメッセージと変更ファイル数で絞れます。次のように頼みます。
このリポジトリの履歴から、一括整形・リネーム・lint自動修正だけのコミットを探して。
git log --oneline --grep と git show --stat を使い、
候補ごとに「変更ファイル数」「ロジックが変わっていない根拠」を表にして。
フルの40桁ハッシュで出し、推測で補わないこと。Claude Codeに履歴を読ませる場面は、git logを渡すパイプ(git log --oneline -20 | claude -p "summarize these recent commits")が公式の例にあります。全履歴ではなく、整形ツールを導入した時期の前後に範囲を絞ると、読ませる量が減ります。
候補は、人が1件ずつ判断します。整形と同じコミットにロジックの変更が混ざっていると、そのコミットを外した瞬間に、本物の変更履歴も隠れます。git show --stat <ハッシュ>で触ったファイルの顔ぶれを見て、整形ツールの設定ファイルだけが別コミットになっているかも確かめてください。
整形だけのコミットかを機械的に確かめる
メッセージが「format」でも、中身にロジックの変更が混ざっていることがあります。候補の1件ごとに、次の3つを見ると判断しやすくなります。
# 変更ファイル数と行数の規模
git show --shortstat --format='%h %s' <ハッシュ>
# 変更したファイルの顔ぶれ(設定ファイルやテストだけでないか)
git show --stat --format= <ハッシュ> | tail -20
# 空白を無視した差分が残るか(残る分は整形以外の変更を含みうる)
git diff -w --stat <ハッシュ>^ <ハッシュ> | tail -5-wを付けた差分が小さいなら、インデント系の整形が中心です。セミコロンの追加や引用符の統一は空白の差ではないので、-wでも差分が残ります。その場合は、整形ツールを親コミットの状態に実行して、差分がそのコミットと一致するかで確かめます。具体的には、親コミットを一時的にチェックアウトし、同じ設定で整形をかけ、git diff <ハッシュ>が空になるかを見ます。Claude Codeには「作業ツリーを汚さないようgit worktreeの別ディレクトリで再現して」と頼むと、手元のブランチに触れずに済みます。
この確認を飛ばすと、ロジックの変更を含むコミットを登録してしまい、その変更の出どころがblameから消えます。登録は、確かめた件だけに絞ってください。
ファイルの書き方
ルート直下に、ファイル名どおりに作ります。GitHubのヘルプが勧める形は、コメント行と40桁ハッシュを交互に並べるものです。
# .git-blame-ignore-revs
# Prettierを全ファイルに適用
442c55873d06f597c66e516afb31b7e1588c5b13
# eslint --fixでimport順を統一
a8940f7fbddf7fad9d7d50014d4e8d46baf30592git configのリファレンスでは、1行に完全なオブジェクト名を1つ書き、空白と#以降のコメントは無視されると説明されています。コメントに「何を整形したか」「どのPRか」を残すと、半年後に増やすときに迷いません。
手元のgitに効かせる
ファイルを置いただけでは、手元のgit blameは読みません。1回の指定なら--ignore-revs-file、常時ならblame.ignoreRevsFileを使います。
git config blame.ignoreRevsFile .git-blame-ignore-revs
git config blame.markIgnoredLines true
git config blame.markUnblamableLines true
git blame util.js^?2cbba7 (dev 2026-10-28 18:47:25 +0900 1) function add(a, b) {
^?2cbba7 (dev 2026-10-28 18:47:25 +0900 2) return a + b;
^?2cbba7 (dev 2026-10-28 18:47:25 +0900 3) }
^2cbba79 (dev 2026-10-28 18:47:25 +0900 4) function sub(a,b){return a-b}整形コミットを外すと、1〜3行目は最初のコミット2cbba79に戻りました。行頭の?は、無視したコミットの影響を受けた行の目印です。blame.markIgnoredLinesは別のコミットに付け替えた行に?を、blame.markUnblamableLinesは付け替え先がない行に*を付ける設定です。この例では先頭の^(最初のコミットの境界)と?が重なって表示されました。目印を付けておくと、整形の影響を受けた行だと見分けられます。
この設定はクローンごとのローカル設定なので、チームの全員に効かせるには、READMEかCLAUDE.mdに1行書いておくのが現実的です。
GitHubのblameビューで確認する
GitHubはルートの.git-blame-ignore-revsを自動で読み、書かれたリビジョンをblameビューから隠します。設定は不要です。ファイルをコミットしてpushしたあと、整形された行を含むファイルのblameを開くと、「Ignoring revisions in .git-blame-ignore-revs」というバナーが出ます。
隠されるのは、そのコミットが行を新規追加または変更した場合です。整形コミットが最後に変えた行は、別のコミットに付け替えられず、blameに残ることがあります。バナーが出ていても、全行が元の作者に戻るとは限りません。
整形で隠されたコミットを見たいときは、URLのSHAの末尾に~を付けます。バナーが消えて、通常のblameになります。
blameが整形コミットのままのとき
- Qリポジトリのルートに.git-blame-ignore-revsがあるか?答えがルートに置き直します。サブディレクトリでは読まれません
整形コミットが最後に変えた行は、blameに残ります。
ハマりやすい落とし穴
落とし穴
短縮ハッシュを書くと実在しない扱いになる
設定の説明は「完全なオブジェクト名(unabbreviated)を1行に1つ」です。空のリポジトリで7桁の短縮ハッシュを入れた別ファイルを--ignore-revs-fileに渡すと、fatal: invalid object nameで止まりました。git log --onelineの出力から貼ると、この失敗になります。git log --format=%Hでフルのハッシュを出してください。
落とし穴
squash マージの前のハッシュを登録する
PRの中で整形コミットを作ってから登録すると、squashやrebaseでマージされた時点で、本流のハッシュは別物になります。登録はマージ後に、mainに載ったハッシュで行います。PRの途中でファイルを書くなら、マージ後に差し替えるPRを1本足す前提で進めます。
実在しないハッシュを検査で止める
Claude Codeにファイルを書かせると、まれに存在しないハッシュが紛れます。登録済みの行がすべてコミットとして実在するか、次のコマンドで確かめられます。
grep -v '^#' .git-blame-ignore-revs | grep -v '^$' | while read h; do
git cat-file -e "$h^{commit}" 2>/dev/null || echo "NG: $h"
done実在するハッシュだけなら何も出力されません。存在しないdeadbeefを混ぜるとNG: deadbeefと表示されました。CIの1ステップにすれば、書き間違いはマージ前に止まります。同じ発想の検査は、CODEOWNERSをgit logから作る記事でも使っています。
新しい整形コミットを足す運用
整形ツールの設定を変えて一括整形するたびに、ファイルへの追記が要ります。CLAUDE.mdに次のように書いておくと、Claude Codeがコミットしたあとに追記を提案しやすくなります。
## 一括整形したとき
- フォーマッタの一括適用や lint 自動修正だけのコミットは、mainに載ったあとの
フルハッシュを .git-blame-ignore-revs に追記する(コメントで内容を1行添える)
- ロジックの変更を同じコミットに混ぜない履歴から決定記録を起こす場面では、整形コミットが邪魔な行を指さなくなります。ADRを後追いで起こす手順や、引き継ぎ資料を作る手順でgit blameを使うなら、先にこのファイルを整えておくと、答えに整形コミットが混ざりません。
まとめ
.git-blame-ignore-revsは、ルートに置く40桁ハッシュの一覧です。GitHubは自動で読み、手元のgit blameにはblame.ignoreRevsFileを設定します。洗い出しはClaude Codeに任せられますが、整形だけのコミットかどうかの判断と、マージ後のハッシュへの差し替えは人の側に残ります。最初に登録するのは、リポジトリで最も大きな一括整形の1件で足ります。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。