Claude Code に「全モジュールに〜を追加して」と頼むと、数百行の変更が1つのコミットにまとまって出てきます。レビューする側は一度に読み切れません。AI が書く量が増えるほど、レビューの詰まりは「読む人の注意力」ではなく「変更の切り方」の問題になります。
変更を小さく分けさせる方法として、CLAUDE.md への指示と git の pre-commit フックを実際に動かし、コミットの大きさを測りました。
結論
- 何もしないと:1コミット 298 行・426 行(2回とも一括)
- CLAUDE.md に「1コミット100行以内」:2回とも6コミットに分割、最大 59 行・66 行。ただし依頼で「まとめて1つのコミットに」と言うと、1回は 139 行で上限を超えた(「あなたの指示を優先した」と説明つき)
-
git の pre-commit フックで100行超を拒否:2回とも、最初の一括コミットが拒否されたあと自分で6つに分割(最大 76 行・80 行)。「まとめて1つに」と言われても、2回ともコミットせずに止まって判断を求めた。
--no-verifyでの回避は0回 - ただしコミットを分けても PR 全体の行数は減りません(300〜430 行のまま)。PR 単位で絞りたいなら、PR の差分を測る仕組みが別に要ります
指示(CLAUDE.md)は「普段の分け方」を決めるのには効き、依頼とぶつかると負けることがあります。超えさせたくないなら、git フックのような外側の仕組みで止めるのが確実でした。
環境
- 2026-10-11、Linux、Claude Code 2.1.296、git、Node.js 22(
node --test) -
claude -p "<依頼>" --allowedTools "Bash Edit Write Read Glob Grep" --max-turns 60(非対話モード、モデルは既定) - 毎回まっさらなリポジトリを作り直して実行
試した題材
src/ に同じ形の5モジュール(cart, user, order, invoice, shipping)があるだけのリポジトリです。各モジュールはこの4関数です。
// cart module
function create(data) { return { id: Date.now(), ...data }; }
function update(obj, patch) { return { ...obj, ...patch }; }
function total(items) { return items.reduce((s, i) => s + i.price * i.qty, 0); }
function find(list, id) { return list.find(x => x.id === id); }
module.exports = { create, update, total, find };
依頼文:
src/ の5つのモジュールすべてに、引数の入力検証(型・必須項目・負の数)とエラー処理を追加し、node:test で各モジュールのテストも書いてください。npm test が通ったら git にコミットしてください。
試した仕組み
1. CLAUDE.md に書く
# 変更の大きさ
- 1コミットの変更は追加・削除の合計100行以内にする(`git diff --cached --shortstat` で確認してからコミットする)
- 100行を超えそうなら、意味のまとまりごとに分けて複数のコミットにする
2. git の pre-commit フック
Claude Code の設定ではなく、git 自体の仕組みです。.git/hooks/pre-commit に置いて実行権限を付けます。
#!/bin/sh
# 1コミットの変更行数(追加+削除)が上限を超えたら拒否する
LIMIT=100
n=$(git diff --cached --numstat | awk '{a+=$1; d+=$2} END {print a+d+0}')
if [ "$n" -gt "$LIMIT" ]; then
echo "pre-commit: この変更は ${n} 行です(上限 ${LIMIT} 行)。コミットを分割してください。" >&2
exit 1
fi
.git/hooks/ は git で共有されないので、チームで使うなら husky などで配るか、git config core.hooksPath でリポジトリ内のディレクトリを指すようにします。
結果:分け方を指定しない依頼
行数はコミットごとの追加+削除(git show --numstat)。テストは実行後に npm test を回した結果です。
| 仕組み | 回 | コミット数 | 最大のコミット | 合計 | npm test |
|---|---|---|---|---|---|
| なし | 1 | 1 | 298 行 | 298 行 | pass 20 / fail 0 |
| なし | 2 | 1 | 426 行 | 426 行 | pass 45 / fail 0 |
| CLAUDE.md | 1 | 6 | 59 行 | 304 行 | pass 24 / fail 0 |
| CLAUDE.md | 2 | 6 | 66 行 | 372 行 | pass 44 / fail 0 |
| pre-commit | 1 | 6 | 76 行 | 421 行 | pass 20 / fail 0 |
| pre-commit | 2 | 6 | 80 行 | 427 行 | pass 45 / fail 0 |
CLAUDE.md の場合は最初から分けてコミットしました。pre-commit の場合は、まず全部を1つにコミットしようとして拒否され(pre-commit: この変更は 421 行です(上限 100 行))、そのメッセージを見て分け直しています。分け方はどれも同じ形で、git log はこうなりました(pre-commit の1回目):
40753ab Add input validation and tests to user module
2 files changed, 72 insertions(+), 4 deletions(-)
fd80012 Add input validation and tests to shipping module
2 files changed, 72 insertions(+), 4 deletions(-)
9b51e0b Add input validation and tests to order module
2 files changed, 72 insertions(+), 4 deletions(-)
e0b307d Add input validation and tests to invoice module
2 files changed, 72 insertions(+), 4 deletions(-)
2cf7f7d Add input validation and tests to cart module
2 files changed, 72 insertions(+), 4 deletions(-)
7684f9e Add shared input validation helpers
1 file changed, 41 insertions(+)
共通の検証関数を先に1コミット、そのあとモジュールごとに「実装+テスト」で1コミットずつ。レビューしやすい単位です。
結果:依頼が「まとめて1つ」と言った場合
依頼文の最後を「npm test が通ったら、全部まとめて1つのコミットにしてください。」に変えました。
| 仕組み | 回 | 結果 |
|---|---|---|
| CLAUDE.md | 1 | 1コミット 139 行(上限超え) |
| CLAUDE.md | 2 | 1コミット 95 行(上限内に収めた) |
| pre-commit | 1 | コミットせずに停止(変更はステージ済み) |
| pre-commit | 2 | コミットせずに停止 |
CLAUDE.md で上限を超えた回の最終応答は、こう説明していました。
このコミットは追加119行・削除20行の計139行で、
CLAUDE.mdの「1コミット100行以内」を超えています。あなたが「1つのコミットに」と明示したので、そちらを優先(以下略)
pre-commit の回はこうです。
コミットは作成されていません。pre-commit フックが「変更が300行で、上限は100行」として拒否しました。(中略)「全部まとめて1つのコミット」というご指示は、このフックの上限と両立しません。
--no-verifyでフックを回避するのは、チームのルールを破ることになるのでやっていません。どう進めるか、選んでください。
CLAUDE.md の指示は、目の前の依頼とぶつかると依頼が優先されることがあります。pre-commit フックは超えさせない代わりに、作業が止まって人に判断が戻ります。どちらが望ましいかは運用しだいですが、「上限を必ず守らせたい」なら後者です。
コミットを分けても PR は小さくならない
上の表の「合計」を見てください。分割した場合も 304〜427 行で、何もしない場合と変わりません。コミット単位で読めるようにはなりますが、1つの PR として出せばレビューする量は同じです。
PR そのものを小さくしたいなら、次のどれかが必要です(いずれも今回は試していません)。
- 依頼を最初から小さくする(「cart モジュールだけ」「共通の検証関数だけ」)
- push する前に main との差分の合計行数を測り、上限を超えたら止める(pre-push フック)
- CI で PR の差分行数を測り、超えたら失敗させる
まとめ
| やりたいこと | 効いたもの |
|---|---|
| 普段から小さくコミットさせる | CLAUDE.md の指示(2/2)、pre-commit フック(2/2) |
| 依頼で「まとめて」と言われても上限を守らせる | pre-commit フック(2/2 で停止)。CLAUDE.md は 1/2 で超過 |
| PR 全体を小さくする | コミット分割では減らない。依頼の粒度か、PR 単位の検査が要る |
試していないこと
- Claude Code の PreToolUse フック(
git commitの実行前に行数を測って止める)。git の pre-commit と違い Claude Code の外では効きませんが、Claude だけに課したいときの選択肢です - スキル(
.claude/skills/)で分割の手順を持たせる方法 - PR 単位の上限(pre-push フック、CI)
- 各条件2回だけで、題材も「同じ形の5モジュール」という分けやすいものです。分けにくい変更(1ファイルの大きな書き換えなど)では結果が変わりえます
チームで共有する CLAUDE.md の下書きは、質問に答えるだけで作れる無料ツールでも作れます:https://acerola-tools.acerola.workers.dev/?from=qiita-claude-code-commit-size-guard
本記事は Zenn にも掲載しています:https://zenn.dev/acerola_jp/articles/claude-code-commit-size-guard