Git 2.54 で導入された Config-based hooks によって、sh スクリプトや husky なしに手軽に Git hooks を構築できます。
同じイベントに複数のフックを設定したり、従来のフックと併用することもできます。
pre-commit は引数がないけど、pre-push は引数を渡されるので、無視する方法を考えました。
pre-push
pre-push イベントは git push を実行した際、リモート参照が更新された後、オブジェクトの転送が始まる前に実行されます。
「リモート名」(例:origin)と「URL」(例:git@github.com:user-name/repository-name.git)を引数にとり、0以外の値を返すと push を中断します。
公式リファレンス
2つの引数
これは複数のリモート先がある場合に活用されるのかな・・?
.git/hooks/pre-push.sample を見てみると、引数は受け取る必要があるので一旦変数に格納してるけど、実質読み捨てているようです。
( WIP(作業中)で始まるコミットメッセージがあると中断するサンプルでした)
remote="$1"
url="$2"
Config-based hooks
Config-based hooks では引数に関するオプションなどがなさそうなので、コマンドの末尾に「 #」を追記して読み捨ててみます。
config を更新するコマンド
% git config hook.runHook true
% git config hook.pre-push-test.event pre-push
% git config hook.pre-push-test.command "npm test #"
.git/config の中身を確認
[hook]
runHook = true
[hook "pre-push-test"]
event = pre-push
command = "npm test #"
package.json の test スクリプトで何かしらテストを呼ぶ
"scripts": {
"test": "node --test"
}
無事、フックからテストコマンドが実行されました( Windows と Mac で確認)
% git push
> test
> node --test
「 #」を入れないと・・
% git config hook.pre-push-test.command "npm test"
引数が node --test に渡されて、エラーになる
% git push
> test ┌─────────────── 不要な引数が渡される ───────────────┐
> node --test origin git@github.com:user-name/repository-name.git
Could not find 'origin, git@github.com:user-name/repository-name.git'
error: failed to push some refs to 'github.com:user-name/repository-name.git'
同じイベントに複数のフックを設定した場合
config に記載された順に実行され、最後に sh スクリプトもあれば実行されます。
git hook list <イベント名> でフック一覧を実行順に確認できます。
% git hook list pre-push
pre-push-lint # config ファイル内で先に書かれている方
pre-push-test # config ファイル内で次に書かれている方
hook from hookdir # 従来の sh スクリプトは最後になる
一時的に無効にする
enabled プロパティで無効化できます
% git config hook.pre-push-lint.enabled false
.git/config
[hook "pre-push-lint"]
command = "npm run lint #"
event = pre-push
enabled = false
リストには disabled がつく
% git hook list pre-push
disabled pre-push-lint
pre-push-test
hook from hookdir
復活させる時は true にするか、
% git config hook.pre-push-lint.enabled true
項目自体を削除(デフォルト true )
% git config --unset-all hook.pre-push-test.enabled
(おまけ)中断理由をメッセージに出したい
フックによりイベントが中断された際、ターミナルや Git ログなどにメッセージが欲しいなと思って、npm スクリプトをこうしてみました。
"scripts": {
"test": "node --test || (echo [error] Test failed. >&2 && exit 1)"
}
|| で、node --test が失敗の時( exit 0 以外の時)に後続のサブシェルを実行。※
>&2 で stderr にリダイレクト。( stdout だと Git ログに出なかったので)
exit 1 であらためてフックに「失敗」を返す。
※ {} グループだと Windows でシンタックスエラーになったのでサブシェルにしました