git のcommit前にlintやらを差し込みたいなということgit hooksを使って設定してみました。
git hooksとは
gitが提供している公式の機能でgitの特定のイベントをトリガーにして自分が設定したscriptを実行させる機構です。
例えば、push前にtestを実行をさせたり、commit前にlintを走らせたりできます。
今回は、commit前にlintを走らせる処理を書きました。
設定方法(pre-commit)
git hooks自体はgitに内蔵されています。
具体的には.gitの中にscriptのサンプルファイルがあります。
terminal でgitで管理しているプロジェクトのrootに移動して
下記のコマンドでhooksファイルがあるディレクトリに移動しましょう。
cd .git/hooks/
すると、以下のファイルがあり、 .sample
という文字列をファイル名が除外して
chmod a+x <ファイル>
と権限を与えればhooksが有効になります。
applypatch-msg.sample fsmonitor-watchman.sample pre-applypatch.sample pre-merge-commit.sample pre-rebase.sample prepare-commit-msg.sample
commit-msg.sample post-update.sample pre-commit.sample pre-push.sample pre-receive.sample update.sample
今回は pre-commitを使いたいので以下の用にリネームします。
pre-commit.sample -> pre-commit
pre-commitのscriptを書く
実際にscriptを書きましょう。
今回はgolang-ci-lintを使って
- lintを実行させる
- formatを実行させる
を行いたいので以下のようにしました。
# !/bin/sh
echo "lint start"
cd $(git rev-parse --show-toplevel)
RESULT=$(golangci-lint run pkg/...)
if [ -n "$RESULT" ]; then
echo "lint failed"
exit 1
fi
git add .
echo "lint finish"
lintの実行場所を固定にする
下記は必ずscriptの実行場所が必ずproject rootになるように、gitの管理場所を取得して、そのディレクトリに移動するようにしています。
git rev-parse --show-toplevel
lintの実行結果を格納
下記はlintの実行結果を格納しています。
これはあまりよろしくなく、本来は終了ステータスを格納すべきですが、誤ってそのまま実行結果の文字列を格納しちゃってます。
RESULT=$(golangci-lint run pkg/...)
強制的にformatをかけてcommitさせる
pre-commit内でgit addしてる理由は、format後のファイルをステージするためにです。
git add .
golangci-lintはauto formatの機能があるので、実際のcommitは以下の処理順番になります。
- git commit コマンドを打つ
- pre-commitが発火
- golangci-lint run pkg/... でファイルにformatがかかる
- git add .
- formatがかかって変更されたファイルが新たにstageされる
- commit 処理が走る
このようにしておくと、formatのかけ忘れなどを防ぐことができます。
管理方法
これでhooksは完成しましたが、.git内にファイルがある関係上このままではgit管理ができません。
なのでhooksファイルとhooksの参照先ファイルを変更します。
変更方法は以下の通り
適当なディレクトリを作り、そこのhooksファイルを移動
mkdir .githooks
mv ./git/hooks/pre-commit .githooks/
gitのhooksファイルの参照先を変更
git config core.hooksPath .githooks
hooksに実行権限を付与
chmod a+x .githooks/pre-commit
これで、hooksファイルの管理場所が.gitでは無くなったのでgit管理できるようになりました。
最後に
hooks といえば husky 自分で作るのは面倒くさいと敬遠していたのですが、重い腰をあげて作ってみると思いのほか簡単にできました。
何かの参考になれば幸いです。
それでは良い git hooksライフを