gitでrebaseに失敗すると辛い気持ちになるので牛に励ましてもらいます (環境はLinuxです)。
方法
以下のスクリプトをgitディレクトリの中に./git/hooks/post-index-changeとして保存します。
#!/bin/bash
comm="$( tr -d '\0' < /proc/$PPID/cmdline )"
if [ "$comm" = "gitrebase--abort" ]; then
# insert your favorite command
cowsay "You failed me."
fi
rebaseをabortすると上のコマンドが実行されます。
$ git rebase --abort
----------------
< You failed me. >
----------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
なおグローバルなgithoooksを設定する方法(参考)を使用すればgitディレクトリの中にスクリプトを置かなくても良くなります。
説明
githooksを利用することでgitのさまざまなポイントに独自の処理(スクリプト)を埋め込むことができます。例えばpre-commitのフックを利用するとコミットの前にコードをフォーマットしたりテストを実行したりすることができます。デフォルトの設定では./git/hooks以下に各フックの名前に対応するスクリプトを用意します。フックの一覧はgithooksのmanページやドキュメントにあります。
さてドキュメントを見てもgit rebase --abort
がフックできるかはよくわかりません。とりあえずフックできるのならばスクリプトをopenしているはずなのでabort時のstraceを確認してみます。
$ strace git rebase --abort 2>&1 | grep ".git/hooks"
access(".git/hooks/post-index-change", X_OK) = -1 ENOENT (No such file or directory)
access(".git/hooks/reference-transaction", X_OK) = -1 ENOENT (No such file or directory)
access(".git/hooks/reference-transaction", X_OK) = -1 ENOENT (No such file or directory)
access(".git/hooks/reference-transaction", X_OK) = -1 ENOENT (No such file or directory)
access(".git/hooks/reference-transaction", X_OK) = -1 ENOENT (No such file or directory)
access(".git/hooks/reference-transaction", X_OK) = -1 ENOENT (No such file or directory)
straceの結果はstderrに出力されるのでgrepするために2>&1
のリダイレクトが必要です。結果よりaccess(2)を使ってpost-idnex-changeとreference-transactionフックのスクリプトの存在を確認している事がわかります(何もフックを設定していない = ファイルが存在しない = -ENOENTのエラー)。reference-transactionは複数呼ばれているのでここではpost-index-changeを利用することにします。
ということで./git/hooks/post-index-changeを用意すれば良いわけですが、名前から推測されるようにgitのindexが変わるたびに呼ばれるフックなのでgit rebase --abort
以外でもこのスクリプトは呼ばれます(abortの例ではabortによりrebaseの途中から元の場所にindexが戻るので呼ばれる)。このため冒頭で示したスクリプトでは親プロセスのcmdlineの値からgit rebase --abort
から呼ばれたかを(無理矢理)判定しています。なお/proc/<pid>/cmdlineからそのPIDのプログラム名と引数の文字列が取得できますが、それらは'\0'で区切られた文字列となっているためtrコマンドで'\0'を削除しています。同様の方法でmerge --abort
やam --abort
もフックできるでしょう。
以上