はじめに
git hookで自動lintをかけるように設定しようーっと思ったのはいいものの、pre-commit, pre-pushしか使った経験がなかったので全体的に"git hookって何?"をまとめてみます.
git hookとは
gitで特定のイベントが発生した時、自動で実行されるスクリプト
- シェルスクリプト、Python Ruby, Node.jsなど
- 実行権限 (chmod+x)が必要
- Exit code = 0 (成功) , 0以外 (失敗)
- デフォルトで
.git/hookに配置
hookの種類
💻 Client-side hooks
Commit系
pre-commit
タイミング: git commit実行時、コミットメッセージ入力前
用途: コード品質チェック、リント、フォーマット
引数: なし
pre-commit-msg
タイミング: デフォルトメッセージ作成後、エディタ起動前
用途: コミットメッセージテンプレート作成
引数:
- コミットメッセージファイルパス
- コミットタイプ(message/template/merge/squash)
- コミットSHA-1(amendの場合)
commit-msg
タイミング: コミットメッセージ入力後、コミット実行前
用途: メッセージフォーマット検証
引数: コミットメッセージファイルパス
⚠️ post-commit
タイミング: コミット完了後
用途: 通知、ログ記録
引数: なし
Merge/Rebase系
pre-merge-commit
タイミング: マージコミット作成前
用途: マージ前の検証
引数: なし
⚠️ post-merge
タイミング: git mergeまたはgit pull後
用途: 依存関係の自動更新
引数: マージがsquash mergeなら1、それ以外は0
pre-rebase
タイミング: git rebase前
用途: rebaseを許可すべきか判断
引数:
- upstream branch
- rebaseされるブランチ(option)
post-rewrite
タイミング: git commit --amendまたはgit rebase後
用途: 履歴書き換え後の処理
引数: コマンド名(amend/rebase)
その他のClient-side hooks
post-checkout
タイミング: git checkout後
用途: ワーキングディレクトリのセットアップ
引数:
- 前のHEAD ref
- 新しいHEAD ref
- ブランチcheckoutなら1、ファイルcheckoutなら0
pre-push
タイミング: git push前、リモート更新前
用途: テスト実行、破壊的操作防止
引数:
- リモート名
- リモートURL
pre-auto-gc
タイミング: git gc --auto前
用途: gc実行を中止したい場合
post-index-change
タイミング: indexが変更された後(git addなど)
用途: IDE連携、自動コンパイル
引数:
- skip-worktreeフラグが変更されたら1、それ以外0
- working treeが変更されたら1、それ以外0
Server-side hooks (リモートレポジトリで実行)
pre-receive
タイミング: リモートでpush受信後、ref更新前
用途: プッシュ全体を許可/拒否
update
タイミング: ref更新前(各refごとに実行)
用途: ブランチ・タグごとのルール適用
引数:
- ref名
- 古いSHA-1
- 新しいSHA-1
⚠️ post-receive
タイミング: push完了後、全ref更新後
用途: デプロイ、通知、CI/CD トリガー
※ ⚠️ はexit code0以外でも特に影響なし (操作がストップしない)
実行フロー
Commitフロー
git commit
↓
pre-commit(コード検証)
↓ exit 0
prepare-commit-msg(メッセージ生成)
↓
[ユーザーがメッセージ入力]
↓
commit-msg(メッセージ検証)
↓ exit 0
[コミット作成]
↓
post-commit(通知など)
Pushフロー(Client)
git push
↓
pre-push(テスト実行)
↓ exit 0
[リモートに送信]
Pushフロー(Server)
[リモートで受信]
↓
pre-receive(全体チェック)
↓ exit 0
update(各refチェック)× N回
↓ exit 0
[ref更新]
↓
post-receive(デプロイ・通知)
Hook管理のベストプラクティス
チーム共有可能にする
# Git 2.9以降(推奨)
git config core.hooksPath .github/hooks
# または自動セットアップ
# composer.json
"scripts": {
"post-install-cmd": [
"git config core.hooksPath .github/hooks"
]
}
# ポイント: プロジェクトルートにhooksを配置してPRでレビュー可能に
パフォーマンス最適化
# ❌ 遅い: 全ファイルチェック
./vendor/bin/phpstan analyse
# ✅ 速い: 変更ファイルのみ
git diff --cached --name-only | xargs ./vendor/bin/phpstan analyse
スキップ可能にする
git commit --no-verify
エラーメッセージを親切に
# ❌ 不親切
echo "Error"
exit 1
# ✅ 親切
cat <<EOF
❌ PHP CS Fixer check failed!
修正方法:
composer fmt
またはスキップ:
git commit --no-verify
EOF
exit 1
参考になれば幸いです🍎