概要
以下のような状況に対応するようなgit hookがほしかったので作ってみました。
- Feature branch を作成し、すぐに WIP 状態で Pull Request を出したい
- Pull Request 出すにはマージ先のブランチとコミット差分が必要
- なので ブランチを切ったら自動で空コミットを作成するhookがほしい
- なおコミットメッセージは "Creat new branch [xxx]" (xxx: 新規作成したブランチ名)とする
以下のような感じのことを自動でやりたいというイメージです。
実装
gistはこちらから
#!/usr/bin/env ruby
before, after, switch = ARGV
exit 0 unless before == after
exit 0 unless switch.to_i == 1
branch = `git rev-parse --abbrev-ref HEAD`
msg = "Created new branch #{branch}"
system(%(git commit --allow-empty -m "#{msg}"))
やっていることは単純で、以下の仕様を単純に実装しただけです。
仕様
今回は post-checkout hookを使って実装します。
post-checkout
ではgit checkout
後に引数として以下の情報をうけとることができます。
-
git checkout
実行前のHEAD (以下B
) -
git checkout
実行後のHEAD (以下A
) - ブランチの変更があったか (0: なし 1: あり) (以下
S
)
今回作成したいのは新しいブランチを作成したら自動で空コミットを1つ作成するhookです。
したがって B == A && S == 1
であれば空コミットを作成するようにしたいと思います。
この条件なら git branch && git checkout
でも git checkout -b
でも、ブランチ作成後、即座にからコミットが作成できるというわけです
問題
しかし、上記の条件では
-
git branch feature
後、別のコミットをcheckoutしてからgit checkout feature
するB!=A
のため空コミットは作られない - 既に
git checkout feature
した状態で、masterにfast forward mergeし、かつcheckoutした後、再びgitc checkout feature
する 既にブランチは作成済みだがB==A
のため空コミットが作られる
いずれも、通常の使用を考えるとそのようなケースは稀だと思い、今回は対応しませんでした。
1 については、逆に空コミットを自動作成されたくない場合の回避策にもなると思います。
ただもっとよい実装があったらぜひ教えてください。
実行
いちおう念のため実行例を載せておきますので、ローカルでリポジトリ作って試してみてください。
$ git log --decorated --graph --oneline --all
* 2fcd02f - (HEAD -> master) Initial commit <imaizume>
$ git cob feature1
Switched to a new branch 'feature1'
[feature1 1c3f519] Created new branch feature1
$ git log --decorated --graph --oneline --all
* 1c3f519 - (HEAD -> feature1) Created new branch feature1 <imaizume>
* 2fcd02f - (master) Initial commit <imaizume>
補足
- Pull Requestも出すなら、そのままhookでpushまでやっても良いと思います。
- ただ自分はブランチ名をtypoすることがあるので、リモートを汚したくないということであえて入れませんでした。
- 自作の際は
chmod u+x post-checkout
するのをお忘れなく - 調べてみると意外とpost-checkout hookに関する情報って無いんですね、あまり使い所がないのかな