チームで共通のフックスクリプト(Git hook)を使っています


サービス開発グループの石川です。
今回のブログでは、チームで共通したGit hookのフックスクリプトによってコミット前のチェックをしている話をしようと思います。

Git hookとは?

Gitで特定のアクションが発生したときにカスタムスクリプトを実行する方法です。
詳細: https://git-scm.com/book/ja/v2/Git-のカスタマイズ-Git-フック

利用しているフックスクリプト

git commitコマンドを実行した際、変更されたファイルをRubocopで解析し、Warning以上の警告がないかをチェックする」というpre-commitファイルを利用しています。(こういった共通したチェックはpush後に通るCI上で実行した方が個人の環境に左右されず良いかもしれませんが、今回は色々理由があってgit hookを使っています。)

#!/bin/sh

# git diffに含まれるrubyファイルに対してrubocopでチェック
# fail level warning以上のもののみをチェックする
if git diff --cached --name-only --diff-filter=AM | grep '\.rb$'; then
  echo '---rubocopでfail-level W以上の警告がないかチェック---'
  git diff --cached --name-only --diff-filter=AM | grep '\.rb$' | xargs  bundle exec rubocop --fail-level W --display-only-fail-level-offenses
fi

推奨されていないメソッドを使っている場合や、デバッグ用のbinding.pryがコードに入ったままといった場合などに気付いて直せるようにすることが目的です。

test/test_helper.rbの中にbinding.pryを含んだ状態でコミットすると、以下の画像のように警告が表示されて問題に気付くことができます。


実際にコミットしたときの画面

他にも、「RedmineやGithubのチケット・Issueにコミットを紐付けるため、コミットメッセージに #nnn のような番号が含まれていることをチェック」などもフックスクリプトを共有すると良さそうです。

チームで共通のGit hookを使う方法

クライアントサイドのフックスクリプトは .git/hooks 以下に置くものなのですが、.git 以下のファイルはバージョン管理されないため .git/hooks もリポジトリで管理することができません。

そのため .githooks という新しく作ったディレクトリの中に共通のフックスクリプトを置き、最初の環境構築時に以下のようなコマンドを各自実行するようにしています。(READMEの環境構築手順の中に書いている)

$ git config --local core.hooksPath .githooks
$ chmod -R +x .githooks/

git config --local core.hooksPath .githooks を実行することで .git/hooksではなく .githooks以下のファイルがフックスクリプトとして実行されるようになります。
https://git-scm.com/docs/githooks

フックスクリプトは実行権限が無いと実行されないため、 chmod -R +x .githooks/ で権限を追加しています。

また、共有するフックスクリプト以外は自由に設定できるように .gitignore に以下のような設定を追加して、 pre-commitのみがステージング対象になるようにしています。

.githooks/*
!/.githooks/pre-commit

core.hooksPath設定を変えることで起こりうる問題

セットアップ時にcore.hooksPathを変えたと言うことを忘れた状態で個人の範囲で .git/hooks にスクリプトを追加した場合、うまく働かず苦しむことになってしまいます。その点を気にするならcore.hooksPathを変えるやり方では無く、以下のようにセットアップ時に手作業で.git/hooksにフックスクリプトをコピーする形にした方が良いです。

$ # githooksを.git/hooksにコピー
$ cp -r githooks .git/hooks

この場合、フックスクリプトを変更しても.git/hooksには変更が反映されない為スクリプトを変更したらチームメンバーにコピーし直すようお願いしないといけませんが、フックスクリプトはそこまで頻繁に変えるようなものでも無いので問題ないと思います。

最後に

コミット前にコードやコミットメッセージをチェックしたい場合には、Git hookのスクリプトを共有すると便利です。共有の仕方については core.hooksPath を変えるやり方と .git/hooks に各自コピーするやり方とがありますが、変更の頻度などに応じて適切なやり方を選ぶと良いと思います。


My Redmine

こちらの記事もオススメです!
Redmineとちょっとした自動化でちょっと幸せに
仕事の中で手間なことや困ったことを、git hooksやRedmineのAPIを活用した"ちょっとした自動化"で解決しています。
My Redmineのバージョンアップ作業をMy Redmineで管理
Redmineの機能「バージョン(ロードマップ)、「親子チケット」、「チケットのコピー」を使ってバージョンアップを管理している事例です。
SmartHRで人事情報の管理を検証中です
人事・労務管理ができるクラウドサービスSmartHR(30名まで無料)で人事情報の管理を行っています。
AWSを利用したハンズオン講座で講師を務めました(資料あり)
AWSを利用したハンズオン講座で講師を務めました。当日は参加者全員が予定していた内容を全て体験することができ、大好評でした!
AWS上でクラウドネイティブで再構築した「My Redmine Gen.2」リリース!
My Redmine Gen.2をリリース!クラウドへの対応を進めより良いサービスになりました。
ファーエンドテクノロジーからのお知らせ(2020/06/03更新)
オープンソースのRedmine互換プロジェクト管理ソフトウェア「RedMica 1.1.0」リリース
Redmine互換のオープンソースのプロジェクト管理ソフトウェア「RedMica」のバージョン1.1.0をリリースしました。
オープンソースのRedmine互換プロジェクト管理ソフトウェア「RedMica」のロゴができました
Redmine互換のオープンソースのプロジェクト管理ソフトウェア「RedMica」(ファーエンドテクノロジー版Redmine)のロゴができました。
2020年度ブランドパートナーに島根県在住のモデル ユイさんを3年連続起用
ユイさん(モデルスタジオミューズ所属)をファーエンドテクノロジーのブランドパートナーとして継続して起用します。今年度で3年目となります。
My Redmine(Gen.2)ストレージ容量を倍増!スタンダードプランは200GBに
My Redmine Gen.2(ジェネレーション2)のストレージ容量が料金そのままにこれまでの2倍になりました。
Redmineの最新情報をメールでお知らせする「Redmine News」配信中
新バージョンやセキュリティ修正のリリース情報、そのほか最新情報を迅速にお届け