先に結論です。AIに自動生成させたコミットメッセージ200件を、Conventional Commitsの規約で分類しました。完全に準拠していたのは86件、43%でした。残りの6割弱は、type選択を間違えるか、subjectが長すぎるか、1コミットに複数の変更を詰め込んでいました。
「AIに任せればコミットメッセージは綺麗になる」。私はそう期待していました。たしかに feat: や fix: の体裁は付きます。差分を見て、それらしいプレフィックスを付けて、それらしい一文を書く。見た目だけなら、人間が雑に書くより整っています。
ですが体裁と中身は別でした。半年後にバグを追うとき、コミット履歴は「何を・なぜ変えたか」を教えてくれる地図になります。その地図として使えるか、という基準で見ると、4割しか合格しませんでした。この記事は、その200件を1件ずつ分類した記録です。
この記事は「コミットメッセージの品質」の話です
線を引きます。Claude CodeのGit操作については前にも書きました。git add や git commit を裏で何をしているか、という操作の解説です。
この記事はそれとは別です。扱うのは、AIが吐き出したコミットメッセージそのものの品質です。規約に沿っているか、typeは正しいか、内容を説明できているか。操作の仕組みではなく、成果物を採点します。
なぜ今これを測ったかというと、AIにコミットまで任せる人が一気に増えたからです。差分を渡せばメッセージが返ってくるので、つい全部任せたくなります。私もそうでした。ですが任せた結果がどんな品質なのかを、誰も数えていない。それなら数えてみよう、というのがこの検証の動機です。
計測条件
推測ではありません。条件を出します。
- 対象: AIコーディングツールが自動生成したコミットメッセージ200件
- 収集元: 私の検証用リポジトリ複数の履歴
- 基準: Conventional Commits 1.0.0 の仕様
- 判定:
type(scope): subject形式・subject 50字以内・命令形・1コミット1論点を満たすか - 分類: 完全準拠 / 部分逸脱 / 非準拠 の3段階を手作業で
「部分逸脱」は、typeは付いているが他の要素を外したもの。「非準拠」は、そもそも type: の形になっていないものです。判定は私が1件ずつ目で確認しました。自動判定では「形式は通るが意図がずれている」type選択ミスを拾えないからです。手作業なのは、そこを正確に数えたかったからです。
結果: 200件の内訳
| 区分 | 件数 | 割合 | 中身 |
|---|---|---|---|
| 完全準拠 | 86 | 43% | 形式・長さ・命令形・1論点すべて満たす |
| 部分逸脱 | 91 | 46% | typeは付くが、長さや論点で外す |
| 非準拠 | 23 | 11% |
type: の形になっていない |
形式だけ見れば、type: が付いていたのは177件(89%)。ほとんどに feat: や fix: は付いていました。ですが「形が整っている」と「規約を満たす」は別で、後者は43%まで落ちました。9割が「準拠っぽく見える」のに、実際に準拠しているのは4割。この差が、AIにコミットを任せたときの実態でした。
具体例を出します。次の3つは、いずれもAIが生成した実際のパターンに近いものです。
# 完全準拠
feat(auth): add password reset endpoint
# 部分逸脱(typeは付くがsubjectが長すぎ・命令形でない)
fix: ユーザー登録時にメールの重複チェックが効いていなかったので修正しました
# 非準拠(type: の形になっていない)
ユーザー登録まわりを色々直した
真ん中の例が曲者です。fix: が付いているので、ぱっと見は準拠しているように見えます。ですがsubjectは50字を超え、命令形でもなく、過去形の報告文になっています。プレフィックスだけで判定すると、これを「準拠」に数えてしまいます。
AIは feat: fix: の見た目をほぼ確実に付けてきます。ですが見た目が付くことと、規約に沿うことは違いました。プレフィックスの有無だけで「準拠している」と判断すると、半分以上を見逃します。
逸脱の3大パターン
部分逸脱・非準拠の114件を分類すると、原因は3つに集中していました。
逸脱114件の内訳は、subject超過41件、type選択ミス38件、複数変更の混在35件。きれいに3つに割れました。
1. subjectが長すぎる(41件)
最多の逸脱です。「fix: ユーザー登録時にメールアドレスの重複チェックが効いていなかった問題を修正しバリデーションを追加」のように、1行に説明を詰め込みます。AIは省略より網羅を選ぶので、subjectが80字を超えることが珍しくありませんでした。50字の壁を、AIは知っていても守りません。
2. type選択のミス(38件)
次に多いのがtypeの取り違えです。新機能なのに chore:、ただのリファクタなのに fix:、設定変更を feat: にする。差分の意味を読み違えると、typeも外れます。特に「動作は変えていないが、見た目を整えた」変更を fix: にしがちでした。fix は「バグの修正」を意味しますが、AIは「何かを直した」を全部 fix に寄せる傾向がありました。リネームやコメント追加まで fix: になっていた例があります。
逆のパターンもあります。本当はバグ修正なのに chore: や refactor: で済ませてしまう。これをやられると、リリースノートを feat/fix から自動生成している現場では、修正がノートから漏れます。typeのミスは、見た目以上に実害があります。
3. 複数の変更を1コミットに混在(35件)
feat: と書きながら、新機能とバグ修正とフォーマット変更が1コミットに同居しているケースです。AIは「セッションでやったことをまとめて1コミットにする」傾向があり、1論点1コミットの原則から外れます。typeが1つに決まらない時点で、規約の前提が崩れています。
これが起きるのは、コミットの単位をAIに任せているからです。1セッションで複数のことをやって、最後にまとめて1コミット。そうすると、その1コミットは何種類もの変更を抱え、feat: という1つのtypeでは説明しきれなくなります。コミットを分ける判断は、差分の意味を理解していないとできません。そしてそれは、今のところ人間の方が得意な作業でした。
typeの分布には偏りがあった
完全準拠した86件のtypeを集計すると、はっきり偏っていました。
| type | 割合 |
|---|---|
| feat | 38% |
| fix | 24% |
| chore | 15% |
| refactor | 9% |
| docs | 7% |
| test | 4% |
| その他 | 3% |
feat と fix で6割を超えます。AIは判断に迷うと、無難な feat か fix に寄せる癖がありました。refactor や test のような、差分の意図を正しく読まないと選べないtypeは、人間が書くより少なめでした。
実際の現場では、テストを追加するコミットも、依存を更新するコミットも、ドキュメントを直すコミットも、それなりの頻度であるはずです。それなのに test が4%、docs が7%しかないのは、AIが「テストの追加」を feat の一部として一緒くたにしているからだと見ています。typeの分布が実態とずれている時点で、後からtype別に履歴を集計しても、正確な数字になりません。
「規約を守る = 良い」とも限らない
ここで皮肉な研究を1つ。2026年に出たセキュリティコミットの大規模調査では、 規約に準拠したコミットの方が、準拠していないコミットより情報量が少ない 傾向が報告されています(On the Informativeness of Security Commit Messages)。
つまり fix: という型に押し込めると、「何を・なぜ直したか」が削られやすい。形式を守ること自体が、説明をやせ細らせる側面があるわけです。型に収める意識が強いほど、型からはみ出す背景説明が捨てられます。
私の200件でも近いことが起きていました。完全準拠した86件の多くは、subjectは綺麗でもbodyが空。「なぜこの変更をしたか」が残っていません。feat(auth): add password reset endpoint は規約としては満点です。ですが「なぜ今これを足したのか」「どんな要望があったのか」は、どこにも書かれていません。規約は通っても、半年後の自分には不親切でした。
ここで大事なのは、規約への準拠率を上げること自体を目的にしない、という視点です。準拠率は測りやすいので、つい指標にしたくなります。ですが本当に欲しいのは「読んで意図が分かる履歴」であって、「規約に通る履歴」ではありません。手段を目的に取り違えると、AIが得意な「形を整える」だけが進んで、人間が握るべき「意図を残す」が置き去りになります。
コミットメッセージの目的は規約を満たすことではなく、後から読む人(未来の自分)に変更の意図を伝えることです。AIに任せると前者は上がりますが、後者は自動では上がりません。
形式はツールで守れる(でも中身は守れない)
ここまでの逸脱のうち、形式まわり(subject超過・type形式)は、実はツールで機械的に弾けます。commitlint を使えば、規約から外れたコミットをコミット時点で止められます。
# commitlint で Conventional Commits 準拠を強制する例
echo "fix: ユーザー登録時のバリデーションが効いていなかった問題を直しました" \
| npx commitlint
# → subject が長すぎる、などの違反を検出して弾く
これを入れれば、形式の準拠率は機械的に100%近くまで上がります。ですが、ここに落とし穴があります。 ツールが守れるのは形式だけ です。typeが内容に合っているか、bodyに「なぜ」が書かれているかは、commitlintには判定できません。
つまり、ツールを入れても「形は整っているが意図が分からない履歴」は量産できてしまいます。形式の準拠と、履歴としての有用さは、別々に守る必要があります。
実務でどう使うか
私の結論は、AIにコミットメッセージを書かせるな、ではありません。 typeとbodyだけは自分で握れ 、です。
具体的には3つにしました。
- 1コミット1論点に、差分の段階で分ける(これはAIに任せず自分でやる)
- AIにはsubjectの叩き台を書かせ、50字に削るのは自分でやる
- 「なぜこの変更をしたか」をbodyに1行足す。ここはAIには書けない
3番目を補足します。AIは差分(what)は読めますが、「なぜそれをしたか(why)」は履歴の外にあります。たとえば「タイムアウトを30秒に延ばした」はAIも書けますが、「本番で外部APIが遅延し、リトライ前にタイムアウトしていたから延ばした」という背景は、その場にいた人間しか知りません。半年後にバグを追うとき効くのは、後者です。
プロンプトの工夫も1つ見つけました。AIにコミットメッセージを頼むとき、「subjectは50字以内、命令形で。bodyには変更の理由を1行。typeに迷うなら候補を2つ挙げて」と添えると、丸投げよりかなりマシになります。完璧にはなりませんが、subject超過は目に見えて減りました。それでも最後のtypeとbodyの確定は、自分の手で握っています。
最初に「布石を打っておくと後が楽になる」のは、コミット履歴でも同じでした。今ていねいに分けておくと、半年後にバグを追うとき、過去の自分に助けられます。私が信長の野望というゲームを長くやっていて染み付いたのは、この「後で効く一手を今打つ」感覚です。コミット履歴は、未来の自分への布石だと思っています。
まとめ
- AI生成コミット200件のうち、規約に完全準拠したのは43%
-
type:の形は89%に付くが、形が整うことと規約を満たすことは別 - 逸脱の3大パターンはsubject超過・type選択ミス・複数変更の混在
- typeは
feat/fixに偏り、AIは迷うと無難なtypeに寄せる - 形式はcommitlintで守れるが、typeの正しさとbodyの「なぜ」は守れない
- 規約準拠でも情報量は増えない。typeとbodyは自分で握るのが現実解
AIに任せる範囲と、自分で握る範囲を分ける。これはコミットメッセージに限らず、AIと組むときの基本だと思っています。全部任せると品質が4割に落ち、全部自分でやると速さの恩恵を捨てる。叩き台はAI、最後の判断は人間。この線引きが、今のところ一番うまくいっています。
AIはコミットの体裁を整えるのは得意です。ですが「なぜ」を残すのは、まだ人間の仕事でした。面白くいきましょう。
AIに開発を任せつつ、コミットやレビューの最後の1割を自分で握る運用は、こちらに詳しくまとめています。
