2026年5月23日
2026年5月23日
GitフックでWP-CLIやコードチェックを自動実行する方法(pre-commit・post-merge・post-receive)
Git フックを使うと、コミットの直前に PHP の構文チェックやコーディング規約チェックを走らせたり、プル後やサーバーへのプッシュ後に WP-CLI のコマンドを自動で実行したりできます。この記事では、WordPress のテーマ・プラグイン開発でよく使う pre-commit、post-merge、サーバー側の post-receive の3つについて、そのまま使えるスクリプト例と、チームで共有する方法、つまずきやすい点を説明します。
Gitフックの基本
Git フックは、コミットやマージなどの操作の前後に Git が自動で実行するスクリプトです。リポジトリの .git/hooks/ に、決まった名前(pre-commit など)で実行権限付きのファイルを置くと有効になります。
押さえておきたい性質は次のとおりです。
pre-で始まるフックは、スクリプトが0以外の終了コードを返すと操作が中止される。チェックに失敗したらコミットさせない、という使い方ができるpost-で始まるフックは操作の後に動くもので、失敗しても操作自体は取り消されない.git/hooks/の中身はリポジトリにコミットされない。そのため、何もしなければフックは自分の手元でしか動かない
最後の点はチーム開発で問題になるため、後半で共有方法を説明します。
pre-commit:コミット前に PHP をチェックする
まずは、コミットしようとしている PHP ファイルだけを対象に php -l(構文チェック)を実行するフックです。構文エラーのあるファイルが本番に出ると画面が真っ白になる事故につながるため、最初に入れておく価値があります。
#!/bin/sh
# .git/hooks/pre-commit
# ステージされた(追加・変更された)PHPファイルだけを対象にする
FILES=$(git diff --cached --name-only --diff-filter=ACM -- '*.php')
[ -z "$FILES" ] && exit 0
STATUS=0
for f in $FILES; do
php -l "$f" > /dev/null || STATUS=1
done
if [ $STATUS -ne 0 ]; then
echo "PHPの構文エラーがあるためコミットを中止しました。"
exit 1
fi
保存したら実行権限を付けます。
chmod +x .git/hooks/pre-commit
ポイントは git diff --cached でステージ済みのファイルだけに絞っていることです。リポジトリ全体をチェックすると、コミットのたびに時間がかかり、使われなくなっていきます。このスクリプトはファイル名に空白が含まれないことを前提にしているので、空白入りのファイル名を扱う場合は書き方を調整してください。
WordPress コーディング規約(PHPCS)を追加する
構文チェックに加えて、PHP_CodeSniffer と WordPress Coding Standards(WPCS)で規約チェックを行うこともできます。Composer で開発用に入れておくと、チーム全員が同じバージョンを使えます。
composer require --dev wp-coding-standards/wpcs
# 導入された規約の一覧に WordPress 系が含まれるか確認
vendor/bin/phpcs -i
Composer のプラグイン許可を求められた場合は、内容を確認したうえで許可します。導入後は、先ほどのフックの末尾に次のような処理を足します。
# pre-commit の続き(ステージされたPHPファイルだけを規約チェック)
vendor/bin/phpcs --standard=WordPress $FILES
if [ $? -ne 0 ]; then
echo "コーディング規約の違反があります。vendor/bin/phpcbf で自動修正できるものもあります。"
exit 1
fi
既存のテーマに後から入れると大量の違反が出ることがあります。その場合は、プロジェクト直下に phpcs.xml.dist を置いて対象ディレクトリや除外ルールを決めてから運用を始めると、無理なく導入できます。
post-merge:プル後に WP-CLI を実行する
git pull でマージが起きた後に動く post-merge フックでは、ローカル開発環境を最新の状態に合わせる処理を自動化できます。たとえば composer.lock が変わっていたら依存関係を入れ直し、WordPress のキャッシュを消す、といった処理です。
#!/bin/sh
# .git/hooks/post-merge
# 直前のマージで composer.lock が変わったか
if git diff --name-only HEAD@{1} HEAD | grep -q '^composer.lock$'; then
echo "composer.lock が更新されたため composer install を実行します"
composer install --no-interaction
fi
# WordPress がインストール済みのときだけ WP-CLI を実行
if wp core is-installed > /dev/null 2>&1; then
wp cache flush
fi
wp core is-installed は、WordPress がインストールされていない環境では0以外を返すので、フックが不要なエラーを出さないためのガードとして使えます。WordPress のディレクトリとリポジトリの位置が異なる場合は、wp --path=/path/to/wordpress cache flush のように --path を指定します。
post-merge では、データベースを書き換えるコマンド(wp search-replace やインポートなど)を自動で走らせるのは避けたほうが安全です。プルのたびに意図せずデータが変わると、原因の切り分けが難しくなります。
post-receive:サーバー側でデプロイ処理を行う
サーバー上にベアリポジトリを置き、そこへ git push したら公開ディレクトリに反映する、という構成では post-receive フックを使います。このフックはプッシュを受け取ったサーバー側で動きます。
#!/bin/sh
# /home/deploy/site.git/hooks/post-receive
TARGET=/var/www/example.com
REPO=/home/deploy/site.git
BRANCH=main
while read oldrev newrev ref; do
if [ "$ref" = "refs/heads/$BRANCH" ]; then
# 反映前にデータベースを書き出す
mkdir -p /home/deploy/backups
wp db export /home/deploy/backups/pre-deploy-$(date +%Y%m%d%H%M%S).sql --path="$TARGET"
# 作業ツリーを最新に
git --work-tree="$TARGET" --git-dir="$REPO" checkout -f "$BRANCH"
# データベースの更新が必要な場合に適用し、キャッシュを消す
wp core update-db --path="$TARGET"
wp cache flush --path="$TARGET"
fi
done
post-receive は標準入力から「古いコミット・新しいコミット・ブランチ名」を1行ずつ受け取るので、対象ブランチへのプッシュのときだけ処理するようにしています。
この方式は手軽ですが、注意点があります。
- ファイルを上書きしている間はサイトが中途半端な状態になる。アクセスの多いサイトでは、リリースごとにディレクトリを分けてシンボリックリンクを切り替える方式のほうが向いている
checkout -fはサーバー上で直接編集された変更を上書きする。本番で直接ファイルを編集しない運用にそろえる- wp-config.php や
wp-content/uploadsはリポジトリに含めず、サーバー側だけで管理する - フックの実行ユーザーとWebサーバーの実行ユーザーが違うと、ファイルの所有者や権限がずれる
まずはステージング環境で同じ構成を作り、プッシュから反映、バックアップの取得までが期待どおりに動くことを確認してから本番に適用してください。
フックをチームで共有する
.git/hooks/ はコミットされないため、チームで同じフックを使うには工夫が必要です。Git 標準の方法は、リポジトリ内のディレクトリをフックの置き場所として指定する core.hooksPath です。この設定は Git 2.9 で追加されたもので、現在一般的に使われている Git であれば利用できます(2026年10月現在)。手元のバージョンは git --version で確認できます。
# リポジトリに .githooks/ を作ってフックを置き、コミットしておく
mkdir -p .githooks
cp .git/hooks/pre-commit .githooks/pre-commit
chmod +x .githooks/pre-commit
# 各メンバーが一度だけ実行する
git config core.hooksPath .githooks
この設定自体は各自のローカル設定なので、README に手順を書くか、Composer の scripts に登録して composer install 時に実行されるようにしておくと漏れを防げます。Node.js を併用しているプロジェクトでは、Husky のようなフック管理ツールを使う方法もあります。
なお、フックは git commit --no-verify で飛ばせます。フックはあくまで手元での早期発見のための仕組みなので、同じチェックを CI(GitHub Actions など)でも実行し、そちらを最終的な関門にするのが一般的です。
フックを運用するときのコツ
- 実行時間を短く保つ。数秒を超えるとメンバーが
--no-verifyを使い始める。重いテストは CI に任せる - 失敗したときは、何が原因でどう直せばよいかをメッセージで示す
- フックの中でファイルを書き換えて自動で
git addする処理は、意図しない変更がコミットに混ざりやすいので慎重に扱う - Windows の Git Bash でも動くよう、
#!/bin/shで書き、改行コードは LF にする
まとめ
- pre-commit では、ステージ済みの PHP ファイルに
php -lとphpcs --standard=WordPressを実行し、失敗したらコミットを止める - post-merge では、composer.lock の変更検知や
wp cache flushなどローカル環境の追従を自動化する。DB を書き換える処理は入れない - post-receive でのデプロイは手軽だが、反映中の不整合や権限のずれに注意し、事前に
wp db exportを取る - フックはコミットされないので、
core.hooksPathで共有し、同じチェックを CI でも実行する