Git高級操作: Git鉤子
Git鉤子是一組腳本,這些腳本對應着Git倉庫中的特定事件,每一次事件發生時,鉤子會被觸發。這允許你可以定製化Git的內部行爲,在開發週期中的關鍵點上觸發執行定製化的腳本。
常見的Git鉤子用法包括:鼓勵某種提交方式,根據倉庫的狀態改變項目環境,以及完善持續集成工作流等。但是既然腳本是可定製化的,那麼也就意味着可以使用Git鉤子來自動化或者優化開發流程中的任一方面。
在本章中我們會先從概念說起。然後我們會考察幾個在本地和服務端最常用的鉤子。
概念概述
所有的Git鉤子都是Git在某個特定事件發生時會執行的腳本。所以其實非常容易安裝並配置。
鉤子可以配置在本地或者服務端倉庫,他們也只會在某些特定動作執行時被觸發。我們會在後面的部分討論鉤子的類別。本節的內容可以應用於本地或者服務端。
安裝鉤子
鉤子腳本文件通常放置於項目目錄的.git/hooks
文件夾下。Git會在初始化項目時自動在這個文件夾下放置一些樣例腳本。如果你查看.git/hooks
文件夾下,會找到如下的文件:
applypatch-msg.sample pre-push.sample
commit-msg.sample pre-rebase.sample
post-update.sample prepare-commit-msg.sample
pre-applypatch.sample update.sample
pre-commit.sample
這些文件基本上涵蓋了可以使用的鉤子,只不過.sample
擴展名不會讓腳本內容生效。安裝一個鉤子最簡單的方式就是刪除.sample
擴展名。或者如果你從頭開始寫好了一個鉤子腳本,只需要將其命名爲上面所列的文件名並去除.sample
擴展名。
舉例來說,安裝一個最簡單的prepare-commit-msg
鉤子腳本。刪除.sample
擴展名,然後添加如下內容:
#!/bin/sh
echo "# Please include a useful commit message!" > $1
鉤子腳本需要可以被執行,所以如果你是從頭新建的腳本,可能需要改變文件權限。比如爲了確保prepare-commit-msg
腳本能夠被執行,你需要執行下面你的命令:
chmod +x prepare-commit-msg
經過設置之後你會發現每次執行git commit
命令時,上面定製化過的提交信息會作爲默認提交信息。我們接下來會在Prepare Commit Message的段落詳細審視這是如何工作的。至於現在只需要明白我們是可以通過鉤子腳本來定製化Git的某些內部功能。
內置的樣例腳本的內容有關於各種鉤子可以傳遞的參數文檔,所以可以作爲創建新腳本的參考。
腳本語言
內置的腳本語言基本上是shell
或者perl
腳本,但是實際上你可以使用任何能夠作爲可執行腳本運行的語言。腳本文件的第一行(#!/bin/sh
)定義了應該使用哪種腳本解釋器。所以要使用其他的語言,只需要將第一行改爲新的執行器的路徑即可。
舉個例子,我們通過修改腳本解釋器路徑,讓prepare-commit-msg
文件執行Python腳本而不是shell命令。
#!/usr/bin/env python
import sys, os
commit_msg_filepath = sys.argv[1]
with open(commit_msg_filepath, 'w') as f:
f.write("# Please include a useful commit message!")
注意第一行被修改爲Python腳本的解釋器。以及我們沒有使用$1
(shell方式)來獲取第一個參數的引用,而是使用了sys.argv[1]
(python方式)(下面會詳細解釋這個地方)
Git提供的這個能力非常強大,這將允許你在創建鉤子的時候,使用任何你{xi}慣的腳本語言。
====================
鉤子的範圍
在指定Git倉庫中,鉤子都是存在於本地的,它們不會跟隨git clone
命令被複制到新的倉庫中去,所以任何對於當前倉庫有權限的人都可以對其進行修改。
這個特性對於爲開發團隊配置鉤子產生了深遠的影響。首先,你需要找到一種方式讓鉤子腳本們在團隊成員之間保持同步。其次,你沒法強制開發者按照指定方式創建提交——只能鼓勵他們這麼做。
爲整個開發團隊維護鉤子有點棘手,因爲.git/hooks
目錄不會像項目的其他部分一樣被git clone
下去,也不在Git的版本管理範疇內。一種簡單的解決方案是把鉤子文件件放在實際項目目錄中(也就是放在.git
目錄之外)。這樣做可以保證他們的行爲與其他被版本管理系統管理的文件一樣。在這種情況下安裝鉤子可以對.git/hooks
路徑創建連接符號(symlink)或者就是簡單拷貝黏貼到.git/hooks
路徑下。