Aqutras Members' Blog

株式会社アキュトラスのメンバーが、技術情報などを楽しく書いています。

gitのフックを使って,コミット時にコードチェックを自動実行するようにした

こんにちは.miです.

弊社ではコードの管理にgitを利用しています. また,コードのチェックツールであるrubocopも利用しており,それをクリアしないものは原則マージされません.

ただ,私がちょくちょくrubocop実行を忘れており,pushしてから気づくということがありました. 一旦pushしてしまうと,それを修正するためのコミットを作って,再度pushして・・・となるので結構面倒です.

これを防ぐ方法として,いっそのことコミット前に自動でrubocopを実行する方法が無いか,調べてやってみたのがこの記事です.

方法

gitのフックを使う

git フックとは

他のバージョンコントロールシステムと同じように、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

pre-commit eslint · GitHub

rubyとかperlでスクリプト書かれている記事もあったので,複雑なものを書くときには(個人的には)そちらが良さそうです.

なにかと必要になるスクリプト力.

思ったよりも簡単に実装できたので,いろいろ試してみたいです.issue番号を自動でコミットメッセージにつけるとか.

ちなみに,フックを実行しないでコミットしたい場合はgit commit --no-verifyとすれば出来ます.

参考

こちらのサイトを参考にさせていただきました.

qiita.com