gitのフックを使って,コミット時にコードチェックを自動実行するようにした
こんにちは.miです.
弊社ではコードの管理にgitを利用しています.
また,コードのチェックツールであるrubocop
も利用しており,それをクリアしないものは原則マージされません.
ただ,私がちょくちょくrubocop実行を忘れており,pushしてから気づくということがありました. 一旦pushしてしまうと,それを修正するためのコミットを作って,再度pushして・・・となるので結構面倒です.
これを防ぐ方法として,いっそのことコミット前に自動でrubocopを実行する方法が無いか,調べてやってみたのがこの記事です.
方法
gitのフックを使う
git フックとは
他のバージョンコントロールシステムと同じように、Gitにも特定のアクションが発生した時にスクリプトを叩く方法があります。フックはクライアントサイドとサーバーサイドの二つのグループに分けられます。クライアントサイドフックはコミットやマージといったクライアントでの操作用に、サーバーサイドフックはプッシュされたコミットを受け取るといったサーバーでの操作用に利用されます。
今回は手元でのフックを行いたいので,クライアントサイドフックを使います.
さらにどこの箇所でフックするかによって,種類が用意されていますが,今回はpre-commit
を使います.
これはコミットメッセージが入力される前に実行されるものです.
ざっくりとした手順
1. ファイル.git/hooks/pre-commit
を作成
.git/hooks/pre-commit.sample
というテンプレートをコピーするか,自分で1から作るかしてください.
2. .git/hooks/pre-commit
を編集
以下が今回作成したスクリプトになります. といってもサンプルに,rubocopを実行して返り値を見るようにする部分を追加しただけです.
#!/bin/bash if git rev-parse --verify HEAD >/dev/null 2>&1 then against=HEAD else # Initial commit: diff against an empty tree object against=4b825dc642cb6eb9a060e54bf8d69288fbee4904 fi # Redirect output to stderr. exec 1>&2 # 今回書いたところ ここから bundle exec rubocop `git diff --staged --name-only` ## 変更のあったファイルに対してrubocopを実行 rubocop_result=$? ## 終了ステータスを変数に取る(別にとらなくてもいいけど) if [ "$rubocop_result" -eq 1 ] ## 異常終了だったらそこで終わり then exit 1 fi # ここまで # If there are whitespace errors, print the offending file names and fail. exec git diff-index --check --cached $against --
3. .git/hooks/pre-commit
に実行権限を付ける
$ chomd +x .git/hooks/pre-commit
4. 実際に使ってみる
rubocopで怒られる状態でコミットしてみて,エラーが出てそこで止まれば成功です.
実行権限が無いと,ファイルが無い状態とおなじになって何も起きません.
まとめ
gitのフックを使う方法を紹介しました.
コミット前に何かをして,その結果によって場合分けというのが簡単に出来ることが分かりました.
今回はrailsプロジェクトだったのでrubocopを使いましたが,jsやcssのケースではeslintやcsslintを使うとか,いろいろ出来そうです.
弊社のMaxMEllonから教えてもらったeslintでチェックするpre-commit
rubyとかperlでスクリプト書かれている記事もあったので,複雑なものを書くときには(個人的には)そちらが良さそうです.
なにかと必要になるスクリプト力.
思ったよりも簡単に実装できたので,いろいろ試してみたいです.issue番号を自動でコミットメッセージにつけるとか.
ちなみに,フックを実行しないでコミットしたい場合はgit commit --no-verify
とすれば出来ます.
参考
こちらのサイトを参考にさせていただきました.