gitでコミット時にコードをフォーマットしてそのままコミットする

上記事によると

for FILE in `git diff --staged --name-only | grep .php`; do
  # ここで言語に応じたなんらかのフォーマット処理
  git add $FILE
done

が提案されているが、ステージングエリアにdeletedがあると formatter の引数にに存在しないファイルが渡されて、 formatterによってはnon-zero exit codeが帰ってきてしまいcommitが行えない (例えば、pythonのフォーマッタ yapf はエラーコードを返す)。

deletedはフォーマットする必要はないので、diffコマンドにフィルタ –diff-filter を追加し、Deletedは削ぎ落とす。その他Unknownも落としておいた。 git-diffのオンラインマニュアルを参照してほしい。

最終的に、yapfでフォーマットする場合は以下のスクリプトを実行権限付きで .git/hooks/pre-commit に書けばよい。

for FILE in `git diff --staged --name-only --diff-filter=ACMRTUB | grep .py`; do
  yapf -i $FILE
  git add $FILE
done