Gitのdiffコマンドにある--exit-codeオプション

npmコマンドでよく書くパターンにGitで固定のファイルをステージしてコミットするというようなものがある。なんらかの処理を行うメインコマンドのpostコマンドでよくやる。まれにその固定のファイルが更新されないこともあり、その時コミットしてしまうとcommitサブコマンドが正常に(終了コード0で)終了しない。これを避けるためにはステージされることで更新があったかどうかをチェックする必要があることになる。それはdiffサブコマンドの--exit-codeオプションを使うとうまく書くことができる。

例えば更新されているかもしれないfooというファイルをステージして、更新があった場合にのみコミットしたい、とすると以下のようにコマンドをつなげれば良い。

$ git add foo && git diff --cached --exit-code --quiet || git commit --message="Update foo"

addサブコマンドでfooをステージした後、diffサブコマンドを、

このように実行すると、差分があった時だけ、つまりfooが更新されていた時だけcommitサブコマンドが走る。またこのコマンド全体の終了コードも0になる(そのためnpmコマンドとして仕込んでもあの長い例外メッセージが出ない)。


Gitのサブコマンドのオプションは単純な機能の制御だけでなく、このようなコマンドやシェルスクリプトを書く上で役に立つものも多くある。しかし必要な時に探すのがすごい大変だ……。てっきりcommitサブコマンドのオプションであるかと(--allow-emptyの逆としてあるかなと推察していた)ずっと探していて、まったく見つからなかった。