Gitフックとは?
Gitフック(Git Hooks)は、Gitの特定のイベントが発生した際に自動的に実行されるスクリプトです。コミット前のコード検証、プッシュ前のテスト実行など、様々な自動化が可能です。
なぜフックが必要?
🤖 品質の自動化
- 「コーディング規約違反のコードがコミットされる」
- 「テストを忘れてプッシュしてしまう」
- 「コミットメッセージが統一されていない」
⏱️ 時間の節約
- 「毎回同じチェックを手動で実行している」
- 「レビューで同じ指摘を繰り返している」
- 「ビルドエラーでCIが失敗する」
フックの種類
クライアントサイドフック
ローカルリポジトリで実行されるフックです。
1. pre-commit
コミット前に実行。コード品質チェックに最適。
#!/bin/sh
# .git/hooks/pre-commit
# ESLintでコードチェック
npm run lint
if [ $? -ne 0 ]; then
echo "❌ Lintエラーが見つかりました。修正してください。"
exit 1
fi
# フォーマットチェック
npm run format:check
if [ $? -ne 0 ]; then
echo "❌ フォーマットエラー。'npm run format'を実行してください。"
exit 1
fi
echo "✅ Pre-commitチェック完了"
2. prepare-commit-msg
コミットメッセージエディタが開く前に実行。
#!/bin/sh
# .git/hooks/prepare-commit-msg
# ブランチ名からIssue番号を抽出してメッセージに追加
BRANCH=$(git branch --show-current)
ISSUE=$(echo $BRANCH | grep -o '[0-9]\+')
if [ -n "$ISSUE" ]; then
sed -i.bak "1s/^/[#$ISSUE] /" "$1"
fi
3. commit-msg
コミットメッセージの検証。
#!/bin/sh
# .git/hooks/commit-msg
# コミットメッセージの形式をチェック
commit_regex='^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .{1,50}'
if ! grep -qE "$commit_regex" "$1"; then
echo "❌ コミットメッセージが規約に従っていません!"
echo "📝 正しい形式: <type>(<scope>): <subject>"
echo "例: feat(auth): ログイン機能を追加"
exit 1
fi
4. pre-push
プッシュ前に実行。最終チェックに使用。
#!/bin/sh
# .git/hooks/pre-push
# テストを実行
echo "🧪 テストを実行中..."
npm test
if [ $? -ne 0 ]; then
echo "❌ テストが失敗しました。修正してください。"
exit 1
fi
echo "✅ すべてのテストが成功しました"
サーバーサイドフック
リモートリポジトリで実行されるフックです。
1. pre-receive
プッシュを受信する前に実行。
#!/bin/sh
# hooks/pre-receive
while read oldrev newrev refname; do
# 大きなファイルをチェック
files=$(git diff --name-only $oldrev $newrev)
for file in $files; do
size=$(git cat-file -s $newrev:$file 2>/dev/null)
if [ $size -gt 10485760 ]; then # 10MB
echo "❌ エラー: $file が10MBを超えています"
exit 1
fi
done
done
フックの実装
基本的なフックの作成
# フックスクリプトを作成
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/sh
echo "🔍 Pre-commitフックを実行中..."
# ステージングされたファイルを取得
files=$(git diff --cached --name-only --diff-filter=ACM | grep '\.js$')
if [ -z "$files" ]; then
exit 0
fi
# 各ファイルをチェック
for file in $files; do
# debuggerが残っていないかチェック
if grep -n "debugger" "$file"; then
echo "❌ エラー: $file にdebuggerが残っています"
exit 1
fi
# console.logが残っていないかチェック
if grep -n "console\.log" "$file"; then
echo "⚠️ 警告: $file にconsole.logが残っています"
fi
done
echo "✅ Pre-commitチェック完了"
EOF
# 実行権限を付与
chmod +x .git/hooks/pre-commit
高度なフック例
セキュリティチェック
#!/bin/sh
# .git/hooks/pre-commit
# APIキーやパスワードのパターンをチェック
patterns=(
"api[_-]?key.*=.*['\"][^'\"]{20,}['\"]"
"password.*=.*['\"][^'\"]+['\"]"
"secret.*=.*['\"][^'\"]+['\"]"
"AWS[_-]?ACCESS[_-]?KEY"
"private[_-]?key"
)
files=$(git diff --cached --name-only)
for file in $files; do
for pattern in "${patterns[@]}"; do
if grep -iE "$pattern" "$file"; then
echo "❌ セキュリティ警告: $file に機密情報が含まれている可能性があります"
echo "パターン: $pattern"
exit 1
fi
done
done
フックの共有
Huksyを使用した共有
// package.json
{
"devDependencies": {
"husky": "^8.0.0"
},
"scripts": {
"prepare": "husky install"
}
}
# Huskyのセットアップ
npm install husky --save-dev
npx husky install
# pre-commitフックを追加
npx husky add .husky/pre-commit "npm run lint"
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'
カスタムフックディレクトリ
# プロジェクトにフックを含める
mkdir .githooks
# pre-commitフックを作成
cat > .githooks/pre-commit << 'EOF'
#!/bin/sh
npm run lint && npm run test:unit
EOF
chmod +x .githooks/pre-commit
# Gitの設定でフックディレクトリを指定
git config core.hooksPath .githooks
実践演習
CommandAcademy Terminal
Welcome to CommandAcademy Terminal!
Type "help" to see available commands.
user@cmdac:~$
█
ファイルツリー
/
etc
hosts35B
passwd76B
home
user
tmp
usr
bin
share
var
log
フックのベストプラクティス
1. パフォーマンスへの配慮
# ❌ 悪い例:すべてのファイルをチェック
find . -name "*.js" | xargs eslint
# ✅ 良い例:変更されたファイルのみチェック
git diff --cached --name-only --diff-filter=ACM | grep '\.js$' | xargs eslint
2. エラーメッセージの改善
# ❌ 悪い例
echo "Error"
exit 1
# ✅ 良い例
echo "❌ ESLintエラー: 以下のファイルを修正してください:"
echo "$failed_files"
echo ""
echo "修正方法: npm run lint:fix"
echo "詳細確認: npm run lint"
exit 1
3. スキップオプションの提供
# 緊急時のスキップを許可
if [ "$SKIP_HOOKS" = "1" ]; then
echo "⚠️ フックをスキップしました"
exit 0
fi
# 使用方法: SKIP_HOOKS=1 git commit -m "緊急修正"
トラブルシューティング
フックが実行されない
# 実行権限を確認
ls -la .git/hooks/
# 実行権限を付与
chmod +x .git/hooks/*
# フックパスを確認
git config core.hooksPath
フックのデバッグ
#!/bin/sh
# デバッグモードを有効化
set -x # コマンドを表示
set -e # エラーで停止
# ログファイルに出力
exec > >(tee -a /tmp/git-hook.log)
exec 2>&1
echo "[$(date)] Hook started: $0"
まとめ
Gitフックは、チームの開発品質を自動的に保つ強力なツールです。適切に設定することで:
- 品質向上: 問題を早期に発見
- 時間節約: 手動チェックを自動化
- 一貫性: チーム全体で同じルールを適用
ただし、過度に厳しいフックは開発速度を落とす可能性があるため、バランスが重要です。
次のレッスンでは、CI/CDとの連携について学ぶ「GitHub Actions/GitLab CI」について学びます。