Git でエンコーディングチェック

Git で、コミット前にファイルのエンコーディングをチェックする pre-commit フックスクリプトを書きました。

いちおう Unix の Git でも Windows の Git でも使えるのと、まだ未完成なのが特徴です。

クロスプラットフォームな開発環境の現場では、リポジトリ内のファイルのエンコーディングは UTF-8 で統一しているのに Shift JIS のファイルをコミットしてしまう Windows ユーザがいたりするので、そういうのを検出してコミットを阻止するのがこのスクリプトの目的です。

ファイルのエンコーディングの判定はたとえば nkf --guess あたりを使えば簡単そうですが、追加のソフトをインストールする手間はかけたくありません。Git があれば必ず利用可能なことが期待できるソフトウェアの中で、ファイルのエンコーディング判定に使えそうなものは Perl くらいです。Windows 環境の Git として一般的な Git for Windows でも Encode モジュールが標準で使える MSYS の Perl 5.8 が同梱されてくるため、これを使えばなんとかなりそうです。

ということで、慣れない Perl スクリプトを書いてみたのがこれです:
https://gist.github.com/2361136/f66c2227d9e1eddea9b3bd0faa51d34e53e7bb2e

スクリプト中で配列 @allowed にコミットを許可するエンコーディングを列挙してください。 @possible の設定は任意です。

このスクリプトを、チェックアウトしたリポジトリに .git/hooks/pre-commit として放りこんで実行権限をつけておけば、コミット時にファイルのエンコーディングの確認をしてくれます。

$ echo -e "\xe3\x81\xbb\xe3\x81\x92" >utf8.txt
$ echo -e "\x82\xd9\x82\xb0" >shiftjis.txt
$ git commit -m "Commiting text files"
shiftjis.txt: shiftjis
Commit aborted! (allowed encodings: ascii utf8)

このようにエンコーディングが @allowed に含まれないと見なされるファイルをコミットしようとしてもできなくなります。いちおう Unix 環境でも Windows 環境でも TortoiseGit を使っていても機能することは確認しました。

現状で対応できてないのはテキストファイルとバイナリファイルの区別です。たいていはエンコーディングが誤判定されてコミットを拒否されますので、その場合は git commit --no-verify としてスクリプトの実行を回避すればコミットできます。

$ curl www.kernel.org/doc/Documentation/logo.gif -o logo.gif
$ git add logo.gif
$ git commit -m "Committing a binary file"
logo.gif: UTF-32BE
Commit aborted! (allowed encodings: ascii utf8)
$ git commit --no-verify -m "Committing a binary file"
[master (root-commit) a63f527] Committing a binary file
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 logo.gif

しかしこれだと、本当に @allowedUTF-32BE が含まれるとき (あるのだろうか?) に区別がつきませんね。スクリプト中で起動している git diff でテキストかバイナリかを判別する方法があればいいのですが。

というわけでこのスクリプトはまだ未完成です。動作報告、バグ報告、改善提案などをお待ちしております。

2012/04/19 追記: バイナリファイルの判定については自己解決しました: Git でバイナリファイル判定

2012/04/23 追記: さらに洗練されたスクリプト集ができました: Git Companion Scripts

2012/04/11 18:24:00 JST