🐶

AIエージェントによる git commit --no-verify を完全に防ぐ方法

に公開

結論

シェル設定ファイルの関数でgitコマンドを上書きすることで、AIエージェントが--no-verifyでhuskyのpre-commitフックを回避する問題を解決できる。

# ~/.zshrc, ~/.bashrc, ~/.config/fish/config.fish など
git() {
    if [[ "$1" == "commit" ]]; then
        for arg in "$@"; do
            if [[ "$arg" == "--no-verify" || "$arg" == "-n" ]]; then
                echo "❌ ERROR: --no-verify bypasses quality checks and is forbidden"
                echo "Pre-commit hooks ensure code quality. Please fix issues instead of bypassing them."
                return 1
            fi
        done
    fi
    command git "$@"
}

この方法により、AIエージェント含む全ての実行環境で--no-verifyの使用を完全に防止し、コード品質を保持できる。

背景

commit時にtest・lintを実行するhuskyでhookしているプロジェクトにおいて、AIエージェントが--no-verifyオプションでこれらの品質チェックを回避する問題が発生していた。

Claude Codeでclaude.mdに--no-verifyオプションを絶対に使用しないように追記しても度々回避された。

また、CodeRabbitによる自動PRレビューもしており、テストが通らないcommitがpushされると指摘が増えて、AIエージェントとCodeRabbitのやり取りが不必要に複雑になる。

検討したアプローチ

❌ 不採用案

1. git aliasによる上書き

git config --local alias.commit '!echo "Alias working, args: $*"; git commit "$@"'

不採用理由: 設定は認識されるが、実行時にaliasが呼ばれず効果がない。

$ git config alias.commit
!echo "Alias working, args: $*"; git commit "$@"
$ git commit -m "test"
# echo出力されず、直接git commitが実行される

2. pre-commit hook強化

# .husky/pre-commit内でチェック
if [[ "$arg" == "--no-verify" ]]; then
    echo "ERROR"
    exit 1
fi

不採用理由: --no-verifyはhuskyのpre-commitフック自体をスキップするため、このチェックも実行されず効果がない。

3. カスタムgitラッパースクリプト

#!/bin/bash
# /usr/local/bin/git
ORIGINAL_GIT="/usr/bin/git"
# --no-verifyをチェック
exec "$ORIGINAL_GIT" "$@"

不採用理由: 環境依存が複雑。Homebrew/Xcode等でgitのパスが異なり、PATH順序変更のリスクもある。

✅ 採用案:シェル関数によるgitコマンド上書き

最終的に採用したのは、シェルの関数でgitコマンドを上書きする方法。

# ~/.zshrc, ~/.bashrc, ~/.config/fish/config.fish など
git() {
    if [[ "$1" == "commit" ]]; then
        for arg in "$@"; do
            if [[ "$arg" == "--no-verify" || "$arg" == "-n" ]]; then
                echo "❌ ERROR: --no-verify bypasses quality checks and is forbidden"
                echo "Pre-commit hooks ensure code quality. Please fix issues instead of bypassing them."
                return 1
            fi
        done
    fi
    command git "$@"
}

採用理由:

  • シンプルで理解しやすい実装
  • 環境依存が少ない
  • 簡単にrollback可能
  • AIエージェント含む全実行環境で有効

実装結果

動作確認

実装後の動作テストを行った:

# ❌ エラーで拒否される
$ git commit --no-verify
❌ ERROR: --no-verify bypasses quality checks and is forbidden
Pre-commit hooks ensure code quality. Please fix issues instead of bypassing them.

# ❌ 短縮オプションも拒否される  
$ git commit -n
❌ ERROR: --no-verify bypasses quality checks and is forbidden
Pre-commit hooks ensure code quality. Please fix issues instead of bypassing them.

# ✅ 正常なcommitは通る
$ git commit -m "test"
# huskyのpre-commitが実行され、成功すればcommit完了

# ✅ その他のgitコマンドも正常動作
$ git status
$ git push

互換性

  • zsh/bash両対応: 両方のシェルで動作確認済み

まとめ

シェル関数によるgitコマンド上書きにより、--no-verifyによる品質チェック回避を完全に防止できた。AIエージェントが賢くなった反面、余計なこともすることも増えている気がするので、AIエージェントが迷走しないようにレールを作ることが重要だと実感した。

Discussion