Gitのフックの説明と挙動の検証

  • 151
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

このドキュメントではフックの説明と、フックの挙動を検証するための方法とその結果を記述する。

フックの説明

Gitは特定のコマンドが実行された場合に、スクリプトを起動させることができる。
そのスクリプトは.git/hooks フォルダに特定の名称で作成することで実行される。

検証プログラム

検証環境は以下の通り
Debian7.0
git version 1.7.10.4

フックの動作を検証するために、各フックスクリプトに下記を記述する。

#!/bin/sh
logger "********************************************"
logger ${0##*/}
logger "param $*"
logger "param cont $#"
logger "input..."
while read i; do
  logger ${i}
done

後は下記のコマンドでsyslogを監視しながらgitの操作を行う

tail -f /var/log/messages

これにより、フックスクリプトの発生順と、パラメータ、標準入力の検証が行える。

フックの確認

commitコマンドのフック

commitコマンドのフックの実行順序は以下の通りである。

1.commit コマンド
2.pre-commitスクリプト実行
3.デフォルトのログメッセージの準備
4.prepare-commit-msgスクリプト実行
5.コミットメッセージ入力用のエディタ起動
6.commit-msgスクリプト実行
7.コミットの作成
8.post-commitスクリプト実行
9.--amendで実行した場合はpost-rewriteスクリプト実行

pre-commit

「git commit」によって呼び出される。commitコマンドに「--no-verify」オプションをつけると呼び出されない。

引数は存在しない。
0以外の終了コードでコマンドを中断する。

prepare-commit-msg

「git commit」によって呼び出される。デフォルトログメッセージの準備が終わった後、そしてエディターが起動する前に呼ばれる。

最大で3つの引数をとる。
第一引数はコミットメッセージを保存したファイルへのパス
第二引数はコミットのタイプである。

Type 説明
なし オプションなし
message -m, -Fオプションがある場合
template -tオプションなどでテンプレートが指定された場合
merge mergeによるコミットの場合
squash --squash オプションでブランチのコミットをまとめた場合
commit -c, -C ,--amendをオプションとして使用した場合。この場合、第三引数にSHA-1が与えられる

0以外の終了コードでコマンドを中断する。

commit-msg

「git commit」によって呼び出される。commitコマンドに「--no-verify」オプションをつけると呼び出されない。

1つの引数を取る
第一引数は現在のコミットメッセージを保存した一時ファイルへのパスになる。

0以外の終了コードでコマンドを中断する。

post-commit

「git commit」によって呼び出される。
引数は存在しない。
コミットを作成したあとに呼ばれ、このスクリプトはgit commit に影響を与えない。
通常、commitの通知に使用される。

post-rewrite

「git commit --amend」や「git rebase」などでコミットログの書き換えが発生された場合に実行される。

引数は1つのみで、amend または rebaseとなる。

また標準入力から以下のデータを取得できる。

<old-sha1> SP <new-sha1> [ SP <extra-info> ] LF

extra-infoはコマンド依存。これが空の場合、前のSPも省略される。

このスクリプトはgit commit に影響を与えない。

am コマンドのフック

git format-patch で作ったパッチを git am で適用する際に実行されるフックの順番は以下のとおりになる。

  1. git am コマンド実行
  2. applypatch-msgスクリプト実行
  3. パッチが適用される
  4. pre-applypatchスクリプト実行
  5. コミットの作成
  6. post-applypatchスクリプト実行

このamコマンドでコミットが作成されても、commit用のフックスクリプトは実行されない。
デフォルトのapplypatch-msgなどは、コミット用のフックスクリプトを実装するサンプルになっている。

applypatch-msg

「git am」コマンド実行時に呼び出される。
引数を一つとり、それはミットメッセージを含む一時ファイル名になる。
0以外の終了コードでコマンドを中断する。

pre-applypatch

「git am」コマンド実行時に呼び出される。
パッチが適用されたのちに、コミットを作成する前に、呼び出される。
引数は存在しない。
0以外の終了コードでコマンドを中断する。

post-applypatch

「git am」コマンド実行時に呼び出される。
パッチが適用され、コミットが作成されたのちに呼び出される。
引数は存在しない。
このスクリプトは「git am」の結果に影響を与えない。
通常は通知に用いられる。

rebaseコマンドのフック

rebaseコマンドを実行する前にpre-rebaseスクリプトが実行される。

その後、次のフックスクリプトが実行されていた。
1.post-checkoutスクリプト実行
2.applypatch-msgスクリプト実行
3.pre-applypatchスクリプト実行
4.post-applypatchスクリプト実行
5.post-rewriteスクリプト実行

2~4はコミットの数だけ複数回。

pre-rebase

rebaseコマンドを実行する前にpre-rebaseスクリプトが実行される。

引数として最大2つ取る。
第一引数は再配置先のブランチ名
第二引数は再配置をするブランチ名で、現在ブランチの場合はブランクになる。

0以外の終了コードでコマンドを中断する。

checkoutコマンドのフック

checkoutコマンドが完了した時にpost-checkoutスクリプトを実行する。

post-checkout

このスクリプトはcheckoutコマンドでワークツリーが更新された後に実行される。
次の3つの引数を取る。
第1引数 変更前のHEADのSHA
第2引数 変更後のHEADのSHA
第3引数 ブランチの変更があったかどうかのフラグ 1:変更あり 0:なし

このスクリプトはコマンドの結果に影響を与えない。

mergeコマンドのフック

mergeコマンドを実行した場合、次の順番でフックメッセージが発生する

  1. prepare-commit-msgスクリプト実行
  2. コミットメッセージの入力
  3. コミットの完了
  4. post-mergeスクリプト実行

post-merge

meregeコマンドが完了されたら実行される。
このスクリプトはsquashマージかどうかの引数を1つだけ与える。
このスクリプトはコマンドの結果に影響を与えない。

pushコマンドのフック

クライアントサイド
1. push コマンドを実行
2. pre-push スクリプトを実行

リモート側
1. クライアントからのpushを受信
2. pre-receiveスクリプトを実行
3. ブランチ単位でそれぞれ一度ずつupdateスクリプトを実行
4. push処理が完了
5. post-receiveスクリプトを実行
6. post-updateスクリプトを実行

pre-push

pushを実行する前にクライアントで実行されるフックスクリプト
未検証。
Version 1.8.2 から。

pre-receive

pushを受信したらリモート上で実行されるスクリプト。
このスクリプトは引数を取らない。
しかし、プッシュされた参照のリストを標準入力から受け取る。
0以外の終了コードでコマンドを中断する。

update

pushを実行した場合update はブランチ単位でそれぞれ一度ずつリモート上で実行される。
3つの引数をとる。
第一引数:関連する参照名 例:refs/heads/master
第二引数:Push前の参照のオブジェクトのSHA
第三引数:新しい参照のSHA

0以外の終了コードでコマンドを中断する

post-receive

pushが完了したらリモート上で一度だけ呼ばれる。
引数はないが、標準入力からpre-receiveと同じ情報が取得できる。
このスクリプトはコマンドの結果に影響を与えない。

このスクリプト中の標準出力(echo)の結果はクライアントに返される。

echo  ECHO POST RECEIVE
root@debian:/share/testgit/hooktest_clone# git push origin test3:master
Counting objects: 5, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 279 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
remote: ECHO POST RECEIVE <<<<< remoteからのメッセージ
To /share/testgit/hooktest
   a8e54a0..437df47  test3 -> master
root@debian:/share/testgit/hooktest_clone#

post-update

すべての参照が実行されたあとにリモート上で呼び出される。
このスクリプトの引数は可変引数となっており、実際に更新された参照(ex. refs/heads/master)が与えられる。
このスクリプトはコマンドの結果に影響を与えない。

このスクリプト中の標準出力(echo)の結果はクライアントに返される。

参考

7.3 Git のカスタマイズ - Git フック
githooks(5) Manual Page