新規にブランチを作成したら自動で空コミットを作成するgit hook

  • 2
    Like
  • 0
    Comment

概要

以下のような状況に対応するようなgit hookがほしかったので作ってみました。

  • Feature branch を作成し、すぐに WIP 状態で Pull Request を出したい
  • Pull Request 出すにはマージ先のブランチとコミット差分が必要
  • なので ブランチを切ったら自動で空コミットを作成するhookがほしい
  • なおコミットメッセージは "Creat new branch [xxx]" (xxx: 新規作成したブランチ名)とする

以下のような感じのことを自動でやりたいというイメージです。

image.png

実装

gistはこちらから

post-checkout
#!/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後に引数として以下の情報をうけとることができます。

  1. git checkout 実行前のHEAD (以下 B)
  2. git checkout 実行後のHEAD (以下 A)
  3. ブランチの変更があったか (0: なし 1: あり) (以下 S)

今回作成したいのは新しいブランチを作成したら自動で空コミットを1つ作成するhookです。
したがって B == A  && S == 1 であれば空コミットを作成するようにしたいと思います。

この条件なら git branch && git checkout でも git checkout -b でも、ブランチ作成後、即座にからコミットが作成できるというわけです :thumbsup:

問題

しかし、上記の条件では

  • git branch feature 後、別のコミットをcheckoutしてからgit checkout featureする :arrow_forward: B!=Aのため空コミットは作られない
  • 既に git checkout feature した状態で、masterにfast forward mergeし、かつcheckoutした後、再びgitc checkout featureする :arrow_forward: 既にブランチは作成済みだが 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するのをお忘れなく :exclamation:
  • 調べてみると意外とpost-checkout hookに関する情報って無いんですね、あまり使い所がないのかな :sweat_smile:

参考リンク