コミット前のlintやテストを毎回手動で実行するのは忘れがち
mise.tomlにlintやテストを実行するタスクを定義していても、コミット前に毎回自分で実行するのは忘れがちである。mise generate git-pre-commitを使うと、コミット時にmise run <タスク名>を自動実行するgit pre-commitフックを生成できる。
mise generate git-pre-commitの基本
mise.tomlにpre-commitタスクを定義したリポジトリで実行する。
$ mise generate git-pre-commit
#!/bin/sh
STAGED="$(git diff-index --cached --name-only -z HEAD | xargs -0)"
export STAGED
export MISE_PRE_COMMIT=1
exec mise run pre-commit "$@"
生成されるシェルスクリプトは、ステージ済みファイルの一覧をSTAGED環境変数にエクスポートしてからmise run pre-commitを実行する。既定では標準出力に表示するだけで、ファイルへの書き込みは行わない。
–writeで.git/hooks/pre-commitに書き込む
-w(--write)を付けると、.git/hooks/pre-commitに書き込まれ、実行権限も付与される。
$ mise generate git-pre-commit --write
Wrote to /path/to/project/.git/hooks/pre-commit
実際にファイルをステージしてコミットすると、フックが実行される。
$ git add bar.txt foo.txt
$ git commit -m "second commit"
[pre-commit] $ echo staged files: $STAGED
staged files: bar.txt foo.txt
[master 5206cb3] second commit
タスク内で$STAGEDを参照すると、コミット対象のファイルだけを取り出して処理できる。
–taskで実行するタスクを変更する
既定ではpre-commitタスクが実行されるが、-t(--task)で別のタスク名を指定できる。
$ mise generate git-pre-commit --task=lint
#!/bin/sh
STAGED="$(git diff-index --cached --name-only -z HEAD | xargs -0)"
export STAGED
export MISE_PRE_COMMIT=1
exec mise run lint "$@"
–hookでpre-commit以外のフックを生成する
--hookを指定すると、.git/hooks/$hookという別のフックとして書き込める。
$ mise generate git-pre-commit --hook=pre-push --write
Wrote to /path/to/project/.git/hooks/pre-push
--hookだけを指定した場合、実行するタスク名はpre-commitのままなので、フックの種類ごとにタスク名も変えたい場合は--taskと組み合わせる。
mise.tomlがリポジトリのルート以外にある場合
git hookは常にリポジトリのトップレベルディレクトリから実行される。mise.tomlがサブディレクトリにある場合、--の後にmiseへ渡す引数を指定すると、miseとrunの間に埋め込まれる。
$ mise generate git-pre-commit -- -C subdir
#!/bin/sh
STAGED="$(git diff-index --cached --name-only -z HEAD | xargs -0)"
export STAGED
export MISE_PRE_COMMIT=1
exec mise -C subdir run pre-commit "$@"
-C subdirを挟むことで、subdir配下のmise.tomlを対象にタスクを実行できる。
より高度なpre-commitが必要な場合
複数タスクの並列実行や、変更されたファイルに応じたタスクの絞り込みなど、より高度な機能が必要な場合はmiseの姉妹プロジェクトであるhk の利用も検討するとよい。
