🪝
Gitのconfig-based hooksをmiseで共有する
Git 2.54 (2026-04-20) で追加されたconfig-based hooksと、miseのremote Git includes機能を使って、複数リポジトリに対してフック設定の共有を簡単にする仕組みを作りました。どんなものをどんなふうに作ったのか、ご紹介します。
実現できたこと
今回の仕組みにより、フックを利用したいリポジトリで mise run enable-git-hooks を実行することで、.git/config に以下の内容が設定されるようになりました。
[hook "validate"]
event = pre-commit
command = ./validate.sh
[hook "dco"]
event = commit-msg
command = "f() { grep -q \"^Signed-off-by: \" \"$1\" || { echo \"Missing Signed-off-by trailer\" >&2; exit 1; }; }; f"
Git 2.54以降であれば、この設定が読み取られ、次のようなコミットが防げます。
-
validate.sh(コードの書式や動作を検証するスクリプト)がエラーになる -
--signoffによる署名を忘れている [1]
どう実現したか
この仕組みは、以下のような手順で実現しました。
miseのタスク設定ファイルを iwamot/mise-tasks に配置
まず、miseのタスクを集約させている iwamot/mise-tasks というリポジトリに、下記のファイルを置きました。
$ cat .mise/tasks/enable-git-hooks
#!/usr/bin/env bash
#MISE description="Enable pre-commit (./validate.sh) and commit-msg (DCO) hooks (requires Git 2.54+)"
set -e
git config hook.validate.event pre-commit
git config hook.validate.command ./validate.sh
git config hook.dco.event commit-msg
git config hook.dco.command 'f() { grep -q "^Signed-off-by: " "$1" || { echo "Missing Signed-off-by trailer" >&2; exit 1; }; }; f'
フックを設定したいリポジトリの mise.toml からリモート参照
そして、フックを設定したいリポジトリの mise.toml で以下の内容を指定し、iwamot/mise-tasks にあるタスク設定をincludeするようにしました。
[task_config]
includes = [
"git::https://github.com/iwamot/mise-tasks.git//.mise/tasks?ref=v1.1.0",
]
これで、mise run enable-git-hooks を実行すると、フックが設定されるようになりました。
なお、同様の手順で disable-git-hooks タスクも作っています。気になる方は、iwamot/mise-tasks リポジトリをご参照ください。
まとめ
- Git 2.54で追加されたconfig-based hooksのおかげで、
git configコマンドでもフックが設定できるようになった - miseタスクをリポジトリに集約し、リモート参照させると、簡単にフック設定が共有できる
-
コマンドを関数で包んでいるのは、Gitが
hook.<name>.commandの文字列の末尾にメッセージファイルのパスを連結してシェルに渡す仕様のためです。構文が壊れないよう、alias.<name>に!付きで複雑なコマンドを設定するときに使われるイディオムを応用しました。 ↩︎
Discussion