⬅️

AIにコミットさせるのは怖いけど、自分でコミットメッセージを考えるのがめんどくさいので楽してみた

に公開1

想定読者

  • AIにコミットまで任せたくないけど、メッセージを書く手間は減らしたい人
  • Conventional Commitsをチームに導入したいが、運用の定着に不安がある人

前提

  • Gitの基本操作(commit, diff, stageなど)ができる
  • Git Hooksの存在を知っている
  • Claude Codeを使用している
  • Conventional Commitsを聞いたことがある
  • これは備忘録である

課題感 — AIにコミットさせたくない、でもメッセージは面倒

  • AIにコミットさせたくない — 何してるかわからないし、プロダクトレベルでは現実的じゃない
  • でもメッセージは適当になりがち — 雑になるし、たまに趣旨とズレてる
  • デザインシステムのチームが始動、パッケージ公開もあるのでPRやコミットを均一化したい → チームメンバーからConventional Commitsを入れようという話に
  • AIがその形式でコミットしてくるのを見て、型が決まってるならdiffから自動生成できそうだと気づいた
  • 最近lefthookを知って、huskyの上位互換的なものだと思っていたので、Git Hooksの管理はこれで試してみようとなった

lefthookとは

Go製のGit Hooks管理ツール。huskyと同様の役割だが、yamlで設定を記述することができたり、高速に動作する優れもの。
詳しくは公式リポジトリを参照。

Conventional Commitsとは

feat(scope): 説明 のようにコミットメッセージの形式を統一する規約。CHANGELOG自動生成やセマンティックバージョニングとの連携がしやすくなる。
詳しくは公式サイトを参照。

Claude Codeでコミットメッセージを自動生成

prepare-commit-msgフックの仕組み

prepare-commit-msg:
  commands:
    generate-commit-msg:
      interactive: false
      run: |
        case "{2}" in
          message|merge|squash)
            exit 0
            ;;
        esac
        claude -p --model claude-haiku-4-5-20251001 "以下のgit diffを見て、Conventional Commits形式のコミットメッセージを1行だけ生成してください。メッセージ本文のみを出力してください。
        形式: <type>(<scope>): <説明>
        typeは feat/fix/docs/style/refactor/test/chore/ci/perf/build のいずれか。
        scopeは変更されたパッケージ名(packages/やapps/配下のディレクトリ名)を使ってください。複数パッケージにまたがる場合は主要なものを1つ選んでください。ルート直下の設定ファイルのみの変更はscopeなしでOKです。
        日本語で書いてください。
        $(git diff --cached)" < /dev/null > {1}

他のツールを使う場合 例:Cursor CLI

lefthookには lefthook-local.yml という仕組みがあり、チーム共有の lefthook.yml を変えずに個人ごとの設定を上書きできる。各自が好みのCLIツールやオプションに差し替えられる。

リポジトリルートに lefthook-local.yml を作成し、コマンドを上書きする:

prepare-commit-msg:
  commands:
    generate-commit-msg:
      interactive: false
      run: |
        case "{2}" in
          message|merge|squash)
            exit 0
            ;;
        esac
        agent -p --model {任意のモデル} "以下のgit diffを見て、Conventional Commits形式のコミットメッセージを1行だけ生成してください。メッセージ本文のみを出力してください。
        形式: <type>(<scope>): <説明>
        typeは feat/fix/docs/style/refactor/test/chore/ci/perf/build のいずれか。
        scopeは変更されたパッケージ名(packages/やapps/配下のディレクトリ名)を使ってください。複数パッケージにまたがる場合は主要なものを1つ選んでください。ルート直下の設定ファイルのみの変更はscopeなしでOKです。
        日本語で書いてください。
        $(git diff --cached)" > {1}

実際にやってみた


大成功です
コミットの中身を確認しつつ、私はコミットメッセージを考えずに済む。これを求めていました

プロンプト設計のポイント

  1. Conventional Commits形式を明示: type一覧を列挙し、scopeのルールも具体的に指定
  2. 1行制約: 「1行だけ」「メッセージ本文のみ」で余計な出力を防止

なぜHaikuモデルか

  • 速度: コミットのたびに呼ばれるため、レスポンス速度が重要。Haikuは数秒で応答する
  • 精度: コミットメッセージの生成はtype/scope判定がメインで、Haikuでも十分な精度

エディタ省略のエイリアス

自動生成されたメッセージをそのまま使いたい場合:

git config alias.cm '!GIT_EDITOR=true git commit'

以降 git cm でエディタなし・メッセージ自動生成のコミットができる。

残された課題

lefthookの売りは「Go製で高速」な点だが、prepare-commit-msgでClaude Codeを呼び出すと、レスポンス待ちで数秒の待機時間がある。高速に動作するのがlefthookのメリットであるが、レスポンス待ちが生じてしまうのは少し残念なところ。

まとめ

  • AIにコミットを丸投げするのではなく、判断は人間が持ったまま面倒な部分だけを委譲する。
  • Git Hooksという既存の仕組みに乗せることで、特別なワークフロー変更なしに導入できるのも嬉しい。

Discussion

ぶりおぶりお

claude -rした際に履歴が汚染されてしまうので、--no-session-persistenceをつけて実行するのが良さそうです