Git Hook開發實踐總結

前言: Git是由Linus大牛在一週時間內開發出來的分佈式版本管理系統,Linux的內核以及各類大小項目都是使用git來管理其版本以及迭代開發。本文將簡要介紹其hook的功能,並通過一個特定的hook實現來展示如何來開發hook。

1 Git Hook

git在提供了一些列版本功能的功能之外,還提供了若干的擴展機制,由開發團隊在其擴展點上根據需要進行定製化功能;例如,提供更爲嚴格的提交規則檢查、comment信息的檢查等等。這些擴展點被成爲Hook,鉤子。
Git 通過Hook的方式,在特定的重要動作發生時觸發自定義腳本。鉤子分類:客戶端的和服務器端。 客戶端鉤子由諸如提交和合並這樣的操作所調用,而服務器端鉤子作用於諸如接收被推送的提交這樣的聯網操作。
客戶端的鉤子,位於git項目的.git/hooks目錄之下:
在這裏插入圖片描述
其中sample結尾的文件是由git提供的hook示例,需要的時候,只需將.sample的後綴移除,即可作爲hook來使用。客戶端的hook示例如下:

  • pre-commit 鉤子在鍵入提交信息前運行。
  • prepare-commit-msg 鉤子在啓動提交信息編輯器之前,默認信息被創建之後運行
  • commit-msg 鉤子接收一個參數,此參數即上文提到的,存有當前提交信息的臨時文件的路徑
  • post-commit 鉤子在整個提交過程完成後運行
    其餘的hook,大家可以自行檢索其應用場景,使用方式大同小異。
    服務端的Hook的擴展點,具體如下:
  • pre-commit: 檢查每次的commit message是否有拼寫錯誤,或是否符合某種規範。
  • pre-receive: 統一上傳到遠程庫的代碼的編碼。
  • post-receive: 每當有新的提交的時候就通知項目成員(可以使用Email或SMS等方式)。
  • post-receive: 把代碼推送到生產環境。
    更多的擴展信息,可以參考git的相關文檔。
    在實際項目中,大家可以根據具體情況,選擇在客戶端/服務端部署hook

2 自定義Hook的功能需求目標

需求描述:

寫一個客戶端鉤子,使得任何一個在master分支上的提交都必須包含JIAR的關鍵字,否則提交不予允許,並給出錯誤提示信息。如果提交發生在非master分支上,則允許提交進行(不管是否包含JIRA關鍵字)

Hook分析:
客戶端Hook,在commit-msg中檢查是否含有JIRA關鍵詞,並檢查Branch是否爲Master。

3 Hook的實現類庫選擇

在本示例中,選用git-python作爲進行git操作的擴展類庫使用,其安裝指令如下:

pip install git-python
在這裏插入圖片描述
當前環境使用的Python版本爲:3.7.0

4 Hook的實現步驟

  1. 新增文件 commit-msg
    文件路徑: .git/hook
    內容如下:
      #!/bin/sh
      python .git/hooks/commit-msg.py $1
    
  2. 新增文件 commit-msg.py
    文件所在的路徑: .git/hooks
import git
import sys, re

repo = git.Repo(search_parent_directories=True)
branch = repo.active_branch

print("currnet branch name:" + branch.name)
print("Start to commit the change in git")

#Required parts
requiredRegex = "JIRA"
requiredLength = 15

#Get the commit file
commitMessageFile = open(sys.argv[1]) #The first argument is the file
commitMessage = commitMessageFile.read().strip()

if branch.name == "master":
    print("Ready to commit the change in master")
    sys.exit(0)

if len(commitMessage) < requiredLength:
    print("Commit message is less than the required 15 characters.")
    sys.exit(1)

if re.search(requiredRegex, commitMessage) is None:
    print("A JIRA Keyword must be filled with a commit")
    sys.exit(1)
    
print("Commit message is validated")
sys.exit(0)

說明:

  1. active_branch指在當前git repository的活躍分支
  2. sys.argv[1]: 從commit-msg命令中傳入的用戶提交的commit註釋信息
  3. sys.exit(0), 0: 表示當前流程正常結束,繼續向下流轉; 1: 中斷當前流程

5 Hook執行效果

在master branch進行提交:
在這裏插入圖片描述
即使在commit信息中未包含JIRA,仍然可以正常提交。

在Dev branch中進行提交:
在這裏插入圖片描述
從其中可以看出,commit信息中未包含JIRA的情況下,提交失敗。

6 異常問題的處理

  1. 無法執行的問題
    提示信息:
  week2 git:(dev) >> git commit -m "test it for hook"
提示:因爲沒有將鉤子 '.git/hooks/commit-msg' 設置爲可執行,鉤子被忽略。您可以通過
提示:配置 `git config advice.ignoredHook false` 來關閉這條警告。
[dev 32f4480] test it for hook

現象分析: commit-msg自定義的鉤子在執行中權限不足,無法被執行。
解決方法:
> chmod +x commit-msg
增加文件的執行權限。

  1. 提示文件不存在的問題
    現象以及問題:
week2 git:(dev) >> git commit -m "test it for hook again"
(null): can't open file 'commit-msg.py': [Errno 2] No such file or directory

現象分析:
無法找到文件,是由於其設置的路徑不正確
解決辦法:
在commit-msg中將執行python文件的路徑設置一下:

#!/bin/sh  
python .git/hooks/commit-msg.py $1

路徑的起點是當前git repository所在的位置。

參考文檔

  1. Git Hook Reference
  2. Git Hook Example
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章