TL;DR
コミットやプッシュなど、Git の操作の決まった時点で自動的に実行されるプログラム。リポジトリの .git/hooks/ に、実行権限を付けて置く。
なぜ必要か
コミットやプッシュの前に、空白のエラーやテストの失敗などを機械的に確かめられる。チェックに通らなければ操作そのものを中止できるので、問題のある変更がリポジトリに入るのを手元で防げる。
仕組み
フックは既定では $GIT_DIR/hooks/ に置く。設定 core.hooksPath で場所を変えられる。実行権限のないファイルは無視される。
操作を止められるフックでは、0 以外の終了コードを返すとその操作が中止される。主なフックは次のとおりである。
pre-commit:git commitでコミットメッセージを受け取る前に実行される。失敗するとコミットが中止されるcommit-msg: コミットメッセージのファイルのパスを受け取り、内容を書き換えたり、コミットを拒否したりできるpre-push:git pushのときに実行され、失敗すると何もプッシュされない
post-commit のような post-* のフックは通知のためのもので、操作の結果は変えられない。
例
#!/bin/sh
# .git/hooks/pre-commit
if git diff --cached --check; then
exit 0
else
echo "Fix whitespace errors before committing." >&2
exit 1
fiEffective Rust 項目32 CIシステムを設定しよう では、秘密情報を誤ってチェックインしていないかの確認は、CI ではなく Git フックでコミット前に行うとしている。Effective TypeScript 項目58 では、pre-push でコードを生成し、git diff で差分が出ないことを確かめる方法が挙げられている。
注意点
pre-commit と commit-msg は、--no-verify を付けると飛ばせる。