Git
章節 ▾ 第二版

8.3 自訂 Git - Git 鉤子

Git 鉤子

如同許多其他版本控制系統,Git 提供在特定重要動作發生時觸發自訂腳本的方法。這些鉤子分為兩組:用戶端和伺服器端。用戶端鉤子由提交和合併等操作觸發,而伺服器端鉤子則在接收推送的提交等網路操作時執行。您可以使用這些鉤子來處理各種原因。

安裝鉤子

鉤子都儲存在 Git 目錄的 hooks 子目錄中。在大多數專案中,該目錄是 .git/hooks。當您使用 git init 初始化新的儲存庫時,Git 會在 hooks 目錄中填入一堆範例腳本,其中許多腳本本身就很有用;但它們也記錄了每個腳本的輸入值。所有範例都以 shell 腳本撰寫,並夾雜一些 Perl,但任何正確命名的可執行腳本都可以正常運作 – 您可以用 Ruby 或 Python 或任何您熟悉的語言撰寫它們。如果您想使用捆綁的鉤子腳本,您必須將它們重新命名;它們的檔案名稱都以 .sample 結尾。

若要啟用鉤子腳本,請在 .git 目錄的 hooks 子目錄中放入一個檔案,該檔案具有適當的名稱(沒有任何副檔名)並且是可執行的。從那時起,它應該會被呼叫。我們將在這裡介紹大多數主要的鉤子檔案名稱。

用戶端鉤子

用戶端鉤子有很多。本節將它們分為提交工作流程鉤子、電子郵件工作流程腳本,以及其他所有內容。

注意

請務必注意,當您複製儲存庫時,不會複製用戶端鉤子。如果您的腳本目的是要強制執行策略,您可能需要在伺服器端執行;請參閱Git 強制策略範例中的範例。

提交工作流程鉤子

前四個鉤子與提交程序有關。

pre-commit 鉤子會先執行,甚至在您輸入提交訊息之前。它用於檢查即將提交的快照,看看您是否忘記了什麼、確保測試執行,或者檢查程式碼中您需要檢查的任何內容。從這個鉤子中以非零值結束會中止提交,但您可以使用 git commit --no-verify 來略過它。您可以執行程式碼樣式檢查(執行 lint 或類似的程式)、檢查尾隨空白(預設鉤子會執行此操作),或檢查新方法是否有適當的文件。

prepare-commit-msg 鉤子會在提交訊息編輯器啟動之前,但在預設訊息建立之後執行。它讓您可以在提交作者看到訊息之前編輯預設訊息。這個鉤子會接收幾個參數:包含目前提交訊息的檔案路徑、提交類型,以及如果這是修改後的提交,則會接收提交的 SHA-1 值。這個鉤子通常對於一般的提交沒有用處;相反地,它適用於預設訊息是自動產生的提交,例如範本化的提交訊息、合併提交、壓縮提交和修改後的提交。您可以將它與提交範本結合使用,以程式化的方式插入資訊。

commit-msg 鉤子會接收一個參數,同樣地,該參數是指向包含開發人員撰寫的提交訊息的暫存檔案的路徑。如果這個腳本以非零值結束,Git 會中止提交過程,因此您可以使用它來驗證專案狀態或提交訊息,然後才允許提交通過。在本章的最後一節,我們將示範如何使用這個鉤子來檢查您的提交訊息是否符合所需的模式。

在整個提交過程完成後,post-commit 鉤子會執行。它不接收任何參數,但您可以透過執行 git log -1 HEAD 輕鬆取得最後一次提交。一般來說,這個腳本用於通知或其他類似用途。

電子郵件工作流程鉤子

您可以為基於電子郵件的工作流程設定三個客戶端鉤子。它們全部都是由 git am 命令調用,所以如果您在工作流程中沒有使用該命令,可以安全地跳到下一節。如果您是透過 git format-patch 準備的電子郵件接收修補程式,那麼其中一些可能會對您有所幫助。

第一個執行的鉤子是 applypatch-msg。它接收一個參數:包含建議的提交訊息的暫存檔案名稱。如果這個腳本以非零值結束,Git 會中止修補程式。您可以使用它來確保提交訊息的格式正確,或透過讓腳本就地編輯訊息來正規化訊息。

透過 git am 應用修補程式時下一個運行的鉤子是 pre-applypatch。有點令人困惑的是,它是在應用修補程式之後但在提交之前運行的,因此您可以使用它來檢查快照,然後再進行提交。您可以使用這個腳本執行測試或以其他方式檢查工作目錄。如果遺失某些東西或測試未通過,則以非零值結束會中止 git am 腳本,而不提交修補程式。

git am 操作期間執行的最後一個鉤子是 post-applypatch,它會在提交完成後運行。您可以使用它來通知一個群組或您提取的修補程式的作者,您已經這樣做了。您無法使用這個腳本停止修補程式過程。

其他客戶端鉤子

pre-rebase 鉤子會在您重定基底任何內容之前執行,並且可以透過以非零值結束來停止該過程。您可以使用這個鉤子來禁止重定基底任何已經推送的提交。Git 安裝的範例 pre-rebase 鉤子會執行此操作,但它會做出一些可能與您的工作流程不符的假設。

post-rewrite 鉤子是由取代提交的命令執行,例如 git commit --amendgit rebase(但不是由 git filter-branch 執行)。它的單一參數是觸發重寫的命令,並且它會在 stdin 上接收重寫清單。這個鉤子具有與 post-checkoutpost-merge 鉤子許多相同的用途。

在您成功執行 git checkout 之後,post-checkout 鉤子會執行;您可以使用它來為您的專案環境正確設定您的工作目錄。這可能表示移入您不想要原始碼控制的大型二進位檔案、自動產生文件或類似的事情。

post-merge 鉤子會在成功執行 merge 命令後執行。您可以使用它來還原 Git 無法追蹤的工作樹中的資料,例如權限資料。同樣地,這個鉤子也可以驗證工作樹變更時您可能想要複製進來、在 Git 控制範圍之外的檔案是否存在。

pre-push 鉤子會在 git push 期間執行,在遠端參考已更新之後,但在任何物件傳輸之前。它會接收遠端的名稱和位置作為參數,以及透過 stdin 傳遞的待更新參考清單。您可以使用它來驗證一組參考更新,然後再進行推送(非零的結束代碼將會中止推送)。

Git 有時會執行垃圾收集,作為其正常操作的一部分,透過調用 git gc --autopre-auto-gc 鉤子會在執行垃圾收集之前被調用,並且可用於通知您正在發生這種情況,或者如果現在不是好時機則中止收集。

伺服器端鉤子

除了客戶端鉤子之外,您還可以身為系統管理員使用幾個重要的伺服器端鉤子,以針對您的專案強制執行幾乎任何類型的原則。這些腳本會在推送到伺服器之前和之後執行。前置鉤子可以隨時以非零值結束,以拒絕推送,並將錯誤訊息印回客戶端;您可以設定複雜的推送原則。

pre-receive

處理來自客戶端的推送時要運行的第一個腳本是 pre-receive。它會接收從 stdin 推送的參考清單;如果它以非零值結束,則不會接受任何參考。您可以使用這個鉤子來執行諸如確保沒有任何更新的參考是非快進之類的操作,或者對所有參考和它們正在使用推送修改的檔案執行存取控制。

update

update 腳本與 pre-receive 腳本非常相似,只是它會針對推送者嘗試更新的每個分支運行一次。如果推送者嘗試推送到多個分支,則 pre-receive 只會運行一次,而 update 則會針對他們推送到的每個分支運行一次。這個腳本不會從 stdin 讀取,而是接收三個參數:參考(分支)的名稱、推送之前參考指向的 SHA-1,以及使用者嘗試推送的 SHA-1。如果 update 腳本以非零值結束,則只會拒絕該參考;其他參考仍然可以更新。

post-receive

post-receive 鉤子會在整個過程完成後運行,並且可用於更新其他服務或通知使用者。它會接收與 pre-receive 鉤子相同的 stdin 資料。範例包括向清單發送電子郵件、通知持續整合伺服器或更新票證追蹤系統 — 您甚至可以剖析提交訊息,以查看是否有任何票證需要開啟、修改或關閉。這個腳本無法停止推送過程,但是客戶端在完成之前不會斷開連線,因此如果您嘗試執行任何可能需要很長時間才能完成的操作,請務必小心。

提示

如果您正在編寫其他人需要閱讀的腳本/鉤子,請優先使用命令列旗標的長版本;六個月後您會感謝我們的。

scroll-to-top