git hooksで pre-commit を自動化し、コミット品質を上げる実践ガイド

本記事では、git hooks の pre-commit フェーズを活用して、コード品質チェック・フォーマット検証・テスト実行を自動化する方法を解説します。開発チーム全体でコミット基準を統一でき、品質低下やリスク要因を事前に防げます。

git hooks と pre-commit が解決する課題

開発チームでよく起こる問題として「未フォーマットのコードがコミットされる」「lint エラーが本番環境で検出される」「テストを実行せずにマージされる」といったことが挙げられます。git hooks の pre-commit フェーズを活用すれば、コミット直前に自動チェックを実行でき、こうした課題を根本的に解決できます。

git hooks は Git リポジトリの .git/hooks ディレクトリに配置されるスクリプトで、特定のイベント(コミット前、プッシュ前など)時に自動実行されます。pre-commit フェーズは「コミットが作成される直前」に動作するため、問題があればコミット自体をブロックできます。

pre-commit フレームワークを使った実装方法

手作業で shell スクリプトを書くこともできますが、実務では pre-commit フレームワーク を導入するのが一般的です。複数の言語・ツールに対応し、設定ファイルで管理でき、チーム全体で自動的に同じルールを適用できます。

インストールと初期設定

まず、pre-commit をインストールしましょう。Python 環境が必要です。

# pip または poetry で pre-commit をインストール
pip install pre-commit

# または
poetry add --group dev pre-commit

# pre-commit のバージョン確認
pre-commit --version

次に、プロジェクトルートに .pre-commit-config.yaml ファイルを作成します。このファイルで実行するチェックを定義します。

# .pre-commit-config.yaml
repos:
  # Python フォーマッター (Black)
  - repo: https://github.com/psf/black
    rev: 24.1.1
    hooks:
      - id: black
        language_version: python3.11

  # Python linter (Ruff)
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.2.0
    hooks:
      - id: ruff
        args: [--fix]

  # YAML フォーマッター
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-merge-conflict

  # Git デフォルト
  - repo: https://github.com/pre-commit/mirrors-prettier
    rev: v3.1.0
    hooks:
      - id: prettier
        types_or: [javascript, jsx, typescript, json, yaml, markdown]

その後、Git フックを実際にセットアップします。

# pre-commit フックをインストール
pre-commit install

# フックがインストールされたか確認
ls -la .git/hooks/ | grep pre-commit

初回実行時に全ファイルをスキャン

既存プロジェクトの場合、初回実行時に過去のコミットまでスキャンすることで、徐々に品質を向上させられます。

# 全ファイルを対象に pre-commit を実行
pre-commit run --all-files

# 特定のフックだけ実行したい場合
pre-commit run black --all-files

実践的なカスタマイズ例

JavaScript / TypeScript プロジェクト向け設定

Node.js ベースのプロジェクトでよく使われる組み合わせです。

# .pre-commit-config.yaml
repos:
  # ESLint
  - repo: https://github.com/pre-commit/mirrors-eslint
    rev: v8.55.0
    hooks:
      - id: eslint
        types: [javascript, jsx, typescript, tsx]
        args: [--fix]

  # Prettier (コード整形)
  - repo: https://github.com/pre-commit/mirrors-prettier
    rev: v3.1.0
    hooks:
      - id: prettier
        types_or: [javascript, jsx, typescript, json, yaml]

  # 共通チェック
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-json
      - id: check-merge-conflict
      - id: detect-private-key

Python プロジェクト向けの高度な設定

型チェック、テスト実行、複数の linter を組み合わせた例です。

# .pre-commit-config.yaml
repos:
  # Black (フォーマッター)
  - repo: https://github.com/psf/black
    rev: 24.1.1
    hooks:
      - id: black
        language_version: python3.11
        args: [--line-length=100]

  # Ruff (高速 linter)
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.2.0
    hooks:
      - id: ruff
        args: [--fix, --exit-non-zero-on-fix]

  # mypy (型チェック)
  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.8.0
    hooks:
      - id: mypy
        args: [--ignore-missing-imports]
        additional_dependencies: [types-all]

  # Bandit (セキュリティチェック)
  - repo: https://github.com/PyCQA/bandit
    rev: 1.7.5
    hooks:
      - id: bandit
        args: [-c, pyproject.toml]
        additional_dependencies: [bandit[toml]]

  # 共通チェック
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.5.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-merge-conflict
      - id: debug-statements
      - id: detect-private-key

よくあるハマりポイントと解決策

「フックが実行されない」場合

pre-commit install を実行していない場合が多いです。まず以下を確認してください。

# フックファイルが正しく生成されているか確認
cat .git/hooks/pre-commit

# 実行権限があるか確認
ls -l .git/hooks/pre-commit

# 権限がない場合は追加
chmod +x .git/hooks/pre-commit

「特定の言語のツールがインストールされていない」エラー

pre-commit は各ツールを独立した環境に自動インストールします。しかし稀にシステム依存関係が不足する場合があります。

# キャッシュをクリアして再実行
pre-commit clean

# フックを再インストール
pre-commit install --install-hooks

# キャッシュをリセット
pre-commit run --all-files --hook-stage commit

「コミットをスキップしたい」場合

緊急時にフックを一時的にバイパスできます(ただし チーム内では慎重に)。

# pre-commit フックをスキップしてコミット
git commit --no-verify

# または環境変数で指定
SKIP=black,ruff git commit -m "message"

「パフォーマンスが遅い」場合

ファイル数が多い場合、pre-commit の実行時間が長くなります。以下の最適化を試してください。

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/psf/black
    rev: 24.1.1
    hooks:
      - id: black
        language_version: python3.11
        # ステージを分けて、コミット時は簡易チェックのみ
        stages: [commit]

  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.2.0
    hooks:
      - id: ruff
        args: [--fix]
        # 特定のファイルのみチェック対象
        exclude: ^(migrations/|tests/)

チーム内での運用方法

.pre-commit-config.yaml をリポジトリに含めることで、開発者全員が同じルールを自動適用できます。

# リポジトリに設定ファイルを含める
git add .pre-commit-config.yaml
git commit -m "Add pre-commit hooks configuration"

# README に セットアップ手順を記載
# 以下を README.md に追加:
# ## Development Setup
# 1. Install pre-commit: pip install pre-commit
# 2. Setup hooks: pre-commit install
# 3. Run initial check: pre-commit run --all-files

新しいメンバーが clone した後、以下を実行するだけで自動的に環境が整います。

# 新メンバーのセットアップ
git clone 
cd 
pre-commit install
pre-commit run --all-files

pre-commit 以外の選択肢との比較

Husky(Node.js)など他のツールもありますが、pre-commit フレームワークの利点は「言語に依存しない」「設定ファイルで一元管理」「公開されたフック レジストリが豊富」の3点です。Python プロジェクトなら pre-commit が、Node.js オンリーなら Husky が候補になります。

使うべき場面と使うべきでない場面

使うべき場面:

  • 複数人で開発するチームプロジェクト
  • コード品質基準が決まっている場合
  • 自動テスト、型チェック、セキュリティスキャンを必須にしたい場合

使うべきでない場面:

  • 個人の学習用スクリプト
  • チェック項目が不安定で頻繁に変わる場合(フックの追加・削除で混乱する)
  • レガシープロジェクトで過度な制約を避けたい場合

よくある質問

いいえ。pre-commit install を実行していない場合、フックは動作しません。チーム全体に導入する場合は、README や CI/CD パイプラインで確実に install させる仕組みが必要です。

問題です。--no-verify は緊急時のみ使用すべきで、習慣的に使うと品質ルールが形骸化します。むしろ「なぜ制約が必要なのか」チーム内で再認識し、不適切なルールはコンセンサスで廃止することをお勧めします。

.pre-commit-config.yaml を編集した後、pre-commit install --install-hooks を実行すれば、最新の設定が反映されます。古い hook は自動削除されないため、必要に応じて pre-commit clean で一度リセットしてください。

まとめ

  • git hooks の pre-commit フェーズを活用することで、コミット前の自動チェックが可能になり、チーム全体のコード品質を向上させられる
  • pre-commit フレームワークを導入すれば、設定ファイル一つで複数のツール(Black、ESLint、mypy など)を一元管理でき、チーム全体で統一されたルールを適用できる
  • 初期セットアップは pre-commit install と .pre-commit-config.yaml の作成のみで、その後は自動的に全開発者に同じルールが適用される
  • パフォーマンスが課題の場合は exclude で対象ファイルを限定した
K
AWS・Python・生成AIを専門とするソフトウェアエンジニア。AI・クラウド・開発ワークフローの実践ガイドを執筆しています。詳しく見る →