githooks(5)
===========
NAME
----
githooks - Hooks(鉤子) used by git
SYNOPSIS
--------
$GIT_DIR/hooks/*
簡介
-----------
Hooks(鉤子),是一些存放于`$GIT_DIR/hooks`文件夾的小腳本,在特定條件下觸發動作.
當執行'git init',幾個示例hook將復制到新資源庫的hooks文件夾, 但默認情況下他們都是禁用狀態.
要啟用一個hook(鉤子),請移除其`.sample`后綴.
注意: 你還需要為這些hook(鉤子)添加可執行權限(譯者注: 僅針對非Windows系統, chmod u+x XXX).
然而,在新創建的資源庫中, - 那些`.sample`默認已經是可執行的(譯者注: 并非如此!!).
本文檔描述的是當前已經等于的hooks(鉤子).
HOOKS(鉤子)
-----
applypatch-msg
~~~~~~~~~~~~~~
這個hook由'git am'腳本觸發. 它將接受一個參數,即將提交的commit msg的臨時文件路徑.
如果這個hook以非0狀態退出,那么'git am'將在patch(補丁)應用之前取消.
這個hook可以用于修改message(信息)文件, 用來匹配項目的規范格式(如果有的話).
也可以用于校驗commit msg,并在必要時拒絕提交.
缺省的'applypatch-msg' hook, 當其啟用時,將調用'commit-msg' hook.
pre-applypatch
~~~~~~~~~~~~~~
這個hook由'git am'腳本觸發. 它并不接受參數, 當patch(補丁信息)已經應用,且commit尚未執行
之前被調用.
如果以非0狀態退出, 那么working tree(工作樹)將不會被提交,但patch已經被應用.
它可以用于檢查當前的working tree(工作樹),當其無法通過某個特定測試時,拒絕進行提交.
缺省的'pre-applypatch' hook, 當其啟用時,將調用'pre-commit' hook.
post-applypatch
~~~~~~~~~~~~~~~
這個hook由'git am'腳本觸發. 它并不接受參數, 在patch已經應用且commit已經完成后執行.
這個hook主要用于通知, 而且對'git am'的輸出無影響.
pre-commit
~~~~~~~~~~
這個hook由'git commit'觸發, 且可以通過`--no-verify` 來略過. 它并不接受參數, 在commit msg被創建之前執行.
如果以非0狀態退出,將導致'git commit'被取消.
缺省的'pre-commit' hook, 當啟用時, 將捕捉以空白字符結尾的行,如果找到這樣的行,則取消提交.
(譯者注: 事實上并非如此,而是查找非ascii文件名!!)
所有的'git commit' hooks在執行時,如果沒有指定編輯器,那么都附帶一個環境變量`GIT_EDITOR=:`
prepare-commit-msg
~~~~~~~~~~~~~~~~~~
這個hook由'git commit',在準備好默認log信息后觸發,但此時,編輯器尚未啟動.
它可能接受1到3個參數.
第一個參數是包含commit msg的文件路徑.
第二個參數是commit msg的來源, 可能的值有:
`message` (當使用`-m` 或`-F` 選項);
`template` (當使用`-t` 選項,或`commit.template`配置項已經被設置);
`merge` (當commit是一個merge或者`.git/MERGE_MSG`存在);
`squash`(當`.git/SQUASH_MSG`文件存在);
`commit`, 且附帶該commit的SHA1 (當使用`-c`, `-C` 或 `--amend`).
如果以非0狀態退出, 'git commit' 將會被取消.
這個hook的目的是修改message文件,且不受`--no-verify`的影響.
本hook以非0狀態退出,則代表當前hook失敗,并取消提交.它不應該取代`pre-commit` hook.
示例`prepare-commit-msg` hook是準備一個merge的沖突列表.
commit-msg
~~~~~~~~~~
這個hook由'git commit'觸發, 且可以通過`--no-verify` 來略過.
它接受一個參數, 包含commit msg的文件的路徑.
如果以非0狀態退出, 'git commit' 將會被取消.
這個hook可以用于修改message(信息)文件, 用來匹配項目的規范格式(如果有的話).
也可以用于校驗commit msg,并在必要時拒絕提交.
缺省的'commit-msg' hook, 當啟用時,將檢查重復的"Signed-off-by"行, 如果找到,則取消commit.
post-commit
~~~~~~~~~~~
這個hook由'git commit'觸發. 它不接受參數, 當commit完成后執行.
這個鉤子主要用于通知,對'git commit'的輸出無影響.
pre-rebase
~~~~~~~~~~
這個hook由'git rebase'觸發,可以用于避免一個分支被rebase.
(譯者注: 原文未提及這個hook的參數數量及作用,下面的說明是我自己加的)
第一個參數, the upstream the series was forked from.
第二個參數(可選), the branch being rebased (or empty when rebasing the current branch).
如果以非0狀態退出,則取消'git rebase'
post-checkout
~~~~~~~~~~~~~
這個hook由'git checkout'觸發, 此時,worktree已經被更新.
這個hook接受3個參數: 之前HEAD的ref,新HEAD的ref,一個標記(1-改變分支,0-恢復文件)
這個hook不會影響'git checkout'的輸出.
它也可以被'git clone'觸發, 僅當沒有使用'--no-checkout (-n)'.
第一個參數是null-ref,第二個參數新的HEAD的ref,第三個參數(flag)永遠為1.
這個hook可以用于進行校驗檢查, 自動顯示前后差異, 或者設置工作目錄的meta屬性.
post-merge
~~~~~~~~~~
這個hook由'git merge'觸發,當'git pull'在本地資源庫執行完畢.
這個鉤子接受一個參數, 一個狀態標記(當前merge順利squash -- 不知道啥意思~_~).
如果合并失敗(沖突),那么這個hook不會影響'git merge'的輸出,且不會被執行.
這個hook用于與pre-commit hook共同使用,以保存并恢復working tree的metadata.
(例如: permissions(權限)/ownership(所有者), ACLS(訪問控制), etc).
請查看源碼中的contrib/hooks/setgitperms.perl,演示了如何使用這個功能.
[[pre-receive]]
pre-receive
~~~~~~~~~~~
這個hook由遠程資源庫的'git-receive-pack'觸發,此時,'git push'已經在本地資源庫執行完畢.
此時,正準備update遠程資源庫的refs,且pre-receive hook已經被觸發并執行完畢.
它的退出狀態,決定了全部ref的update是否可以進行.
這個hook,每個接收操作,僅執行一次. 它不接受參數,但可以從標準輸入讀取以下格式的文本(每個ref一行):
<old-value> SP <new-value> SP <ref-name> LF
這里的 `<old-value>` 是ref中原本的Object名,
`<new-value>` 是ref中老的Object名 and
`<ref-name>` 是ref的全名.
當創建一個新ref,`<old-value>` 將是 40, 即字符`0`.
(譯者注: SP=空格, LF=\n)
如果這個hook以非0狀態退出,則所有ref都不會被更新(update).
如果以0退出, 仍可以通過<<update,'update'>> hook 來拒絕特定的ref的更新.
hook的標準輸入/標準輸出,均導向'git send-pack',所以,你可以簡單地使用`echo`來為用戶打印信息.
(譯者注: 就是本地push后打印出來的信息)
[[update]]
update
~~~~~~
這個hook由遠程資源庫的'git-receive-pack'觸發,此時,'git push'已經在本地資源庫執行完畢.
此時,正準備update遠程資源庫的ref.
它的退出狀態,決定了當前ref的update是否可以進行.
每個將要update的ref,都會觸發一次這個hook, 它接受3個參數:
- 將要被update的ref的名字,
- ref中老object的名字,
- 將要存儲的ref的新名字.
以0狀態退出,將允許當前ref被update.
以非0狀態退出,將防止'git-receive-pack'更新當前ref.
這個hook可以用于防止特定的ref被'force'更新..
就是說,可以確保"fast-forward only"這一安全準則.
它也可以用于記錄新舊狀態. 然而, 它并不知道整體的分支狀態,所以它可能被天真地用于為每個ref發送email.
<<post-receive,'post-receive'>> hook更適合做這個需求哦.
另外一個用法是使用這個hook實現訪問控制, 而不僅僅通過文件系統的權限控制.
hook的標準輸入/標準輸出,均導向'git send-pack',所以,你可以簡單地使用`echo`來為用戶打印信息.
(譯者注: 就是本地push后打印出來的信息)
缺省的'update' hook, 當啟用,且`hooks.allowunannotated`配置項未設置或設置為false時,防止未聲明的tag被更新.
[[post-receive]]
post-receive
~~~~~~~~~~~~
這個hook由遠程資源庫的'git-receive-pack'觸發,此時,本地資源庫的'git push'已經完成,且所有ref已經更新.
這個hook僅執行一次. 它不接受參數,但跟<<pre-receive,'pre-receive'>> hook獲取相同的標準輸入格式.
這個hook并不影響'git-receive-pack'的輸出,因為它在實際工作完成之后執行.
跟<<post-update,'post-update'>> hook不一樣的是,這個hook可以拿到ref在update前后的值.
hook的標準輸入/標準輸出,均導向'git send-pack',所以,你可以簡單地使用`echo`來為用戶打印信息.
(譯者注: 就是本地push后打印出來的信息)
缺省的'post-receive' hook 是空白的, 但提供了一個示例腳本`post-receive-email`,位于源碼中的`contrib/hooks`
目錄,實現了發送commite mails的功能.
[[post-update]]
post-update
~~~~~~~~~~~
這個hook由遠程資源庫的'git-receive-pack'觸發,此時,本地資源庫的'git push'已經完成,且所有ref已經更新.
它接受可變數量的參數, 每一個參數都是已經實際update的ref的名字.
這個hook主要是為了統治, 無法影響'git-receive-pack'的輸出.
'post-update' hook可以知道哪些ref已經被push,但無法知道原本及更新后的值,
所以它不是一個好地方去處理新舊變化.
<<post-receive,'post-receive'>> hook 可以拿到新舊兩個值. 你可以考慮使用它們.
默認的'post-update' hook,啟用后,將允許'git update-server-info'來更新無狀態傳輸(例如http)的信息.
如果你通過HTTP協議來公開git資源庫,那么你很可能需要啟用這個hook.
hook的標準輸入/標準輸出,均導向'git send-pack',所以,你可以簡單地使用`echo`來為用戶打印信息.
(譯者注: 就是本地push后打印出來的信息)
pre-auto-gc
~~~~~~~~~~~
這個hook由'git gc --auto'觸發. 它不接受參數, 非0狀態退出,將導致'git gc --auto'被取消.
(譯者注: 有一個示例contrib/hooks/pre-auto-gc-battery,演示了在電池狀態(筆記本電腦沒插電源)時,拒絕執行git gc的功能)
post-rewrite
~~~~~~~~~~~~
這個hook由改寫commit的命令所觸發(`git commit
--amend`, 'git-rebase'; 當前 'git-filter-branch' 并'不'觸發它!!).
它的第一個參數,表示當前是什么命令所觸發:`amend` 或 `rebase`.
也許將來會傳遞更多特定于命令的參數.
這個hook通過標準輸入接收rewritten commit的列表,格式如下:
<old-sha1> SP <new-sha1> [ SP <extra-info> ] LF
其中'extra-info'是命令本身所決定的,如果為空,那么前置的SP(空格)也不存在.
當前沒有任何命令會使用'extra-info'.
這個hook總是在自動note copying之后只需(請參看 "notes.rewrite.<command>" in linkgit:git-config.txt).
以下是特定命令的附加注釋:
rebase::
'squash' and 'fixup'操作, 所有提交(squashed)將重寫進squashed commit.
這意味著多行squash將使用同一個new-sha1'.
+
在列表中的commits的順序,嚴格符合與傳遞給rebase的順序.
譯者后記:
1. hook列表:
------------------------------------------------------
|鉤子名字 |觸發命令 |參數|非0導致取消|備注|
|applypatch-msg |git am |1 |Yes||
|pre-applypatch |git am |0 |Yes||
|post-applypatch |git am |0 |No ||
|pre-commit |git commit |0 |Yes||
|prepare-commit-msg|git commit |1~3 |Yes||
|commit-msg |git commit |1 |Yes||
|post-commit |git commit |0 |No ||
|pre-rebase |git rebase |2 |Yes||
|post-checkout |git checkout|3 |No ||
|post-merge |git merge |1 |No ||
|pre-receive |git-receive-pack |0 |Yes|通過標準輸入獲取信息|
|update |git-receive-pack |3 |Yes||
|post-receive |git-receive-pack |0 |No |通過標準輸入獲取信息|
|post-update |git-receive-pack |可變|No ||
------------------------------------------------------
2. hook的示例
雖然示例中,hook都是perl腳本,但絕對不表示只能用perl.只要是可執行的東西,都可以作為鉤子
3. 源碼級別的hook信息
我非常神奇地發現, hook的名字,并沒有獨立寫在某個h文件中,而是分布于幾個具體的c文件中
主執行入口: run_hook(const char *index_file, const char *name, ...) 定義于run-command.h,實現于run-command.c
官方說明:
`run_hook`::
Run a hook.(執行一個hook)
The first argument is a pathname to an index file, or NULL(第一個參數是index file,可能為NULL)
if the hook uses the default index file or no index is needed.
The second argument is the name of the hook.(第二個參數是hook的名字)
The further arguments correspond to the hook arguments.(剩下的,就是hook自己需要的參數了)
The last argument has to be NULL to terminate the arguments list.(最后一個參數必須是NULL,C的常識性用法)
If the hook does not exist or is not executable, the return
value will be zero.(當hook不存在或不可執行,則返回0 )
If it is executable, the hook will be executed and the exit
status of the hook is returned. (方法的返回值,就是hook的退出狀態)
On execution, .stdout_to_stderr and .no_stdin will be set.
(See below.)
GIT
---
Part of the linkgit:git[1] suite