Git のクライアントフック管理ベストプラクティス

本当はもっといろいろ考えたが、わりと一般的な方法に落ち着いてしまった。

フック管理の問題点

フックスクリプトの管理は .git/hooks 以下と決まっている。 .git 以下にあるので、当然このスクリプトはバージョン管理されない。 なので、自分の作業環境のフックは自由に変更可能だが、プロジェクト内で同じフックを共有することは出来ない。

無視ファイルの管理(.gitignore)などはプロジェクトで共有可能であるにも関わらず、フックスクリプトの管理で同じことが出来ないのは、個人的に腑に落ちない。

ベストプラクティスの紹介

ディレクトリ直下に .hooks というディレクトリを用意する。 この下に必要なフックスクリプトを配置する。 ディレクトリ直下なので、配置したスクリプトはバージョン管理される。 ファイル名先頭にドットを付けるかは悩ましいところだが、 .gitignore と同列と考えれば付けるのが正しいと思う。

さらに、core.hooksPath に .hooks ディレクトリのパスを与える。(※1) この作業は、初期設定手順としてプロジェクト内で共有する。 ここが一番の妥協点で、新規に加入したメンバーやディレクトリを作り直したメンバーが手順を飛ばす可能性があるのだが、 まあ、手順は README に書いておけば普通は見るはずだし、Git の場合 Submodule や Git LFS のような初見殺しの拡張機能も普通にあるので、もともと手順に依存するのは避けられないんじゃないかと思う。(※2)

  • ※1: 2.9 以後のバージョンなら core.hooksPath に対応しているので、git config core.hooksPath path/to/.hooks すれば良い。
  • ※2: この辺りの拡張機能は本当に初見殺しなので、クライアントアプリ側でいい感じに対応してほしいところ。

ツールを使っても幸せになれない

最後に、ツールについて触れて置く。

Git のフック管理のユーティリティツールとしては、 overcommitgit-hooks が有名である。 どちらも「Git クライアントのフック管理が弱い」という名の下に開発されているツールだと思うのだが、 いかんせんフック管理に対する十分な解決策を提示できているかというとそうではなく、 いまひとつ流行っていないというのがその証拠だと思う。

.git/hooks 以外にスクリプトを置けないという仕様上、 結果的にシンボリックリンクディレクトリ単位で貼るしかないわけで、 その程度であればツールという依存性を増やすくらいなら、 各メンバーが初期設定の一手順としてリンクを貼った方が簡単なのである。

もちろん、これらのツール群には便利な機能がいくつも実装されているので、そう言った機能を使いたい(もしくは、既に依存している)というプロジェクトにとっても有用な選択肢となるだろう。

フックスクリプトのハブ的なものがあるべき?

静的解析をかけたり、NG ワードをチェックしたりと、フックスクリプトで行う処理ってわりと共通しているはずなので、 実装を共有できる仕組みがあるべきなのかなあと言うアイデアがもともとあった。 しかし、プロジェクトごとに事情が細かく違っているし、そう言う事情を吸収するのは結構難しいはず。プロジェクトごとに個別に実装するのが落とし所だと言う結論に今は至っている。一人が実装すればプロジェクト全体で使えるし、それくらいの実装は肩慣らしくらいの気持ちでやっちゃえばいいんじゃないかと思う。