git-hooks-automation について
開発中にコードチェックを実行する Git hooks の設定を支援するスキルです。ネイティブ hooks、lint-staged と Husky、pre-commit、カスタムスクリプト、CI での検証を扱います。
主な機能
- 01pre-commit と pre-push hooks の設定
- 02lint-staged によるステージ済みファイルの検査
- 03コミットメッセージ規約の適用
- 04Husky または pre-commit の導入
- 05CI での hooks 検証
活用シーン
- 01コミット前の lint とフォーマット適用
- 02プッシュ前のテスト実行
- 03Git hooks の導入や移行
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill git-hooks-automationインストール後、Claude Code で/git-hooks-automationを入力して読み込まれたか確認します。
詳細
Git フックの自動化
Git レベルでコード品質のチェックを自動化します。コミットやプッシュが CI パイプラインに到達する前に、フックで lint、フォーマット、テスト、検証を行うよう設定すれば、問題を数分ではなく数秒で見つけられます。
このスキルを使用する場面
- ユーザーが「git hooks の設定」や「pre-commit hooks の追加」を依頼したとき
- Husky、lint-staged、または pre-commit フレームワークを設定するとき
- コミットメッセージの規約(Conventional Commits、commitlint)を徹底するとき
- コミット前の lint、フォーマット、型チェックを自動化するとき
- テストランナー用の pre-push フックを設定するとき
- Husky v4 から v9+ への移行、またはフックを新規導入するとき
- ユーザーが「pre-commit」、「commit-msg」、「pre-push」、「lint-staged」、「githooks」に言及したとき
Git フックの基本
Git フックは、Git のワークフロー内の特定のタイミングで自動的に実行されるスクリプトです。.git/hooks/ に保存されますが、デフォルトではバージョン管理されません。そのため、Husky のようなツールが使われます。
フックの種類と実行タイミング
| フック | 実行タイミング | 一般的な用途 |
|---|---|---|
pre-commit | コミットの作成前 | ステージ済みファイルの lint、フォーマット、型チェック |
prepare-commit-msg | デフォルトのメッセージ設定後、エディターを開く前 | コミットテンプレートの自動入力 |
commit-msg | ユーザーがコミットメッセージを記述した後 | コミットメッセージの形式を徹底 |
post-commit | コミットの作成後 | 通知、ログ記録 |
pre-push | リモートへのプッシュ前 | テストの実行、ブランチポリシーの確認 |
pre-rebase | リベースの開始前 | 保護されたブランチでのリベースを防止 |
post-merge | マージの完了後 | 依存関係のインストール、マイグレーションの実行 |
post-checkout | チェックアウト/切り替え後 | 依存関係のインストール、アセットの再ビルド |
Git 標準のフック(フレームワークなし)
# Create a pre-commit hook manually
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/sh
set -e
# Prefer installed lint-staged: it handles filenames and partially staged files.
# Do not run whole-file fixes followed by git add: that can stage unrelated edits.
npx --no -- lint-staged
EOF
chmod +x .git/hooks/pre-commit
問題点:.git/hooks/ はローカル環境にしか存在せず、チームと共有されません。代わりにフレームワークを使用してください。
Husky + lint-staged(Node.js プロジェクト)
JavaScript/TypeScript プロジェクトでの現在の標準です。Husky が Git フックを管理し、lint-staged が速度を上げるためにステージ済みファイルに対してのみコマンドを実行します。
クイックセットアップ(Husky v9+)
# Install
npm install --save-dev husky lint-staged
# Initialize Husky (creates .husky/ directory)
npx husky init
# The init command creates a pre-commit hook — edit it:
echo "npx lint-staged" > .husky/pre-commit
package.json で lint-staged を設定する
{
"lint-staged": {
"*.{js,jsx,ts,tsx}": [
"eslint --fix --max-warnings=0",
"prettier --write"
],
"*.{css,scss}": [
"prettier --write",
"stylelint --fix"
],
"*.{json,md,yml,yaml}": [
"prettier --write"
]
}
}
コミットメッセージの lint を追加する
# Install commitlint
npm install --save-dev @commitlint/cli @commitlint/config-conventional
# Create commitlint config
cat > commitlint.config.js << 'EOF'
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [2, 'always', [
'feat', 'fix', 'docs', 'style', 'refactor',
'perf', 'test', 'build', 'ci', 'chore', 'revert'
]],
'subject-max-length': [2, 'always', 72],
'body-max-line-length': [2, 'always', 100]
}
};
EOF
# Add commit-msg hook
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg
Pre-Push フックを追加する
# Run tests before pushing
echo "npm test" > .husky/pre-push
Husky のディレクトリー構成全体
project/
├── .husky/
│ ├── pre-commit # npx lint-staged
│ ├── commit-msg # npx --no -- commitlint --edit $1
│ └── pre-push # npm test
├── commitlint.config.js
├── package.json # lint-staged config here
└── ...
pre-commit フレームワーク(Python/複数言語)
あらゆるプロジェクトで使える、言語に依存しないフレームワークです。フックは YAML で定義され、分離された環境で実行されます。
セットアップ
# Install (Python required)
pip install pre-commit
# Create config
cat > .pre-commit-config.yaml << 'EOF'
repos:
# Built-in checks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-json
- id: check-added-large-files
args: ['--maxkb=500']
- id: check-merge-conflict
- id: detect-private-key
# Python formatting
- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
- id: black
# Python linting
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.4
hooks:
- id: ruff
args: ['--fix']
- id: ruff-format
# Shell script linting
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.10.0.1
hooks:
- id: shellcheck
# Commit message format
- repo: https://github.com/compilerla/conventional-pre-commit
rev: v3.2.0
hooks:
- id: conventional-pre-commit
stages: [commit-msg]
EOF
# Install hooks into .git/hooks/
pre-commit install
pre-commit install --hook-type commit-msg
# Run against all files (first time)
pre-commit run --all-files
主なコマンド
pre-commit install # Install hooks
pre-commit run --all-files # Run on everything (CI or first setup)
pre-commit autoupdate # Update hook versions
pre-commit run <hook-id> # Run a specific hook
pre-commit clean # Clear cached environments
フックはローカルのコードを実行します。サードパーティ製のフックと固定されたリビジョンを、インストール前に確認してください。ローカルフックは回避可能であり、マージの承認にはなりません。以下の移植可能なカスタム例は、意図的に簡略化されています。行単位のパス処理では特殊なファイル名に対応できず、作業ツリー上のファイルサイズはステージ済み blob のサイズと異なり、差分コンテキストのスキャンでは削除された行やコンテキスト行に一致したり、シークレットが漏えいしたりすることがあります。NUL セーフな方法でステージ済み blob を調査し、一致したシークレットの値を出力せずにファイル名とルールを報告してください。
カスタムフックスクリプト(任意の言語)
Node や Python を使用しないプロジェクトでは、シェルで直接フックを記述します。
移植可能な Pre-Commit フック
#!/bin/sh
# .githooks/pre-commit — Team-shared hooks directory
set -e
echo "=== Pre-Commit Checks ==="
# 1. Prevent commits to main/master
BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo "detached")
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "master" ]; then
echo "❌ Direct commits to $BRANCH are not allowed. Use a feature branch."
exit 1
fi
# 2. Check for debugging artifacts
if git diff --cached --diff-filter=ACM | grep -nE '(console\.log|debugger|binding\.pry|import pdb)' > /dev/null 2>&1; then
echo "⚠️ Debug statements found in staged files:"
git diff --cached --diff-filter=ACM | grep -nE '(console\.log|debugger|binding\.pry|import pdb)'
echo "Review the staged changes and follow repository policy."
exit 1
fi
# 3. Check for large files (>1MB)
LARGE_FILES=$(git diff --cached --name-only --diff-filter=ACM | while read f; do
size=$(wc -c < "$f" 2>/dev/null || echo 0)
if [ "$size" -gt 1048576 ]; then echo "$f ($((size/1024))KB)"; fi
done)
if [ -n "$LARGE_FILES" ]; then
echo "❌ Large files detected:"
echo "$LARGE_FILES"
exit 1
fi
# 4. Check for secrets patterns
if git diff --cached --diff-filter=ACM | grep -nEi '(AKIA[0-9A-Z]{16}|sk-[a-zA-Z0-9]{48}|ghp_[a-zA-Z0-9]{36}|password\s*=\s*["\x27][^"\x27]+["\x27])' > /dev/null 2>&1; then
echo "🚨 Potential secrets detected in staged changes! Review before committing."
exit 1
fi
echo "✅ All pre-commit checks passed"
core.hooksPath でカスタムフックを共有する
# In your repo, set a shared hooks directory
git config core.hooksPath .githooks
# Add to project setup docs or Makefile
# Makefile
setup:
git config core.hooksPath .githooks
chmod +x .githooks/*
CI との統合
フックは最初の防御線ですが、正とするべきものは CI です。
CI で pre-commit を実行する(GitHub Actions)
# .github/workflows/lint.yml
name: Lint
on: [push, pull_request]
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- uses: pre-commit/[email protected]
CI で lint-staged を実行する(検証のみ)
# Validate that lint-staged would pass (catch bypassed hooks)
name: Lint Check
on: [pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx eslint . --max-warnings=0
- run: npx prettier --check .
よくある問題と解決方法
フックが実行されない
| 症状 | 原因 | 解決方法 |
|---|---|---|
| フックが警告なしにスキップされる | .git/hooks/ にインストールされていない | npx husky init または pre-commit install を実行する |
| 「Permission denied」 | フックファイルに実行権限がない | chmod +x .husky/pre-commit |
| フックは実行されるが、想定と異なるものが実行される | 古い設定のフックが残っている | git config core.hooksPath を確認し、対象を絞った修復の前に無関係なフックを保持する |
| ローカルでは動作するが、CI では失敗する | Node/Python のバージョンが異なる | CI 設定でバージョンを固定する |
パフォーマンスの問題
// ❌ Slow: runs on ALL files every commit
{
"scripts": {
"precommit": "eslint src/ && prettier --write src/"
}
}
// ✅ Fast: lint-staged runs ONLY on staged files
{
"lint-staged": {
"*.{js,ts}": ["eslint --fix", "prettier --write"]
}
}
フックのバイパス(必要な場合)
# Skip all hooks for a single commit
git commit --no-verify -m "wip: quick save"
# Skip pre-push only
git push --no-verify
# Skip specific pre-commit hooks
SKIP=eslint git commit -m "fix: update config"
Warning: フックのバイパスはまれに行うべきです。チームで頻繁にバイパスしている場合、フックが遅すぎるか、厳しすぎます。修正してください。
移行ガイド
Husky v4 → v9 の移行
# 1. Remove old Husky
npm uninstall husky
# Back up and inspect existing .husky scripts; remove only obsolete generated files
# 2. Remove old config from package.json
# Delete "husky": { "hooks": { ... } } section
# 3. Install fresh
npm install --save-dev husky
npx husky init
# 4. Recreate hooks
echo "npx lint-staged" > .husky/pre-commit
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg
# 5. Clean up — old Husky used package.json config,
# new Husky uses .husky/ directory with plain scripts
既存のプロジェクトへのフックの導入
# Step 1: Start with formatting only (low friction)
# lint-staged config:
{ "*.{js,ts}": ["prettier --write"] }
# Step 2: Add linting after team adjusts (1-2 weeks later)
{ "*.{js,ts}": ["eslint --fix", "prettier --write"] }
# Step 3: Add commit message linting
# Step 4: Add pre-push test runner
# Gradual adoption prevents team resistance
主な原則
- ステージング済みのファイルのみ — コミットのたびにコードベース全体を lint しないでください
- 可能な場合は自動修正 —
--fixフラグを使うと、開発者の手間を減らせます - 高速なフック — pre-commit は 5 秒未満で完了するようにしてください
- 明確なエラー表示 — 対処可能な修正方法を含む、わかりやすいエラーメッセージを表示します
- チームで共有 — Husky または
core.hooksPathを使って、フックをバージョン管理します - CI をバックアップとして活用 — フックは利便性のためのものです。強制力を持つのは CI です
- 段階的に導入 — まずフォーマットから始め、lint を追加し、その後テストを追加します
関連するスキル
@codebase-audit-pre-push- GitHub への push 前の詳細な監査@verification-before-completion- 作業完了を宣言する前の検証@bash-pro- カスタムフック向けの高度なシェルスクリプト@github-actions-templates- CI/CD ワークフローのテンプレート
制限事項
- タスクが上記の説明にある範囲に明確に一致する場合に限り、このスキルを使用してください。
- 出力を、環境固有の検証、テスト、または専門家によるレビューの代わりとして扱わないでください。
- 必要な入力、権限、安全上の境界、または成功基準が不足している場合は、作業を中断して確認してください。