推薦學習:《》
Git 除了版本控制,還有一些其他的高階功能,其中之一就是Git Hooks,明面意思就是勾點,可以類比於勾點函數。簡單說就是Hook會在做某些事情的前後被勾點鉤走去一些額外事情,那麼這些額外事情我們可以用作於檢查、測試和部署等操作。
在 Git 中有許多的事件(commit、push 等等),每個事件也是對應了有不同的勾點的(如 commit 前,commit 後),那麼我們就可以在這些勾點這裡設定一些自己需要執行的操作來實現各種各樣的需求。
Git hooks 是 Git 在事件之前或之後執行的指令碼, 用於控制 git 工作的流程。Git hooks 指令碼對於我們提交code review
之前識別一些簡單的問題很有用。 我們在每次提交程式碼時都會觸發這些 hooks,以自動指出程式碼中的問題,例如缺少分號,尾隨空白和偵錯語句。通過在code review
之前指出這些問題,程式碼審閱者可以專注於程式碼結構和功能的更改,而不需要浪費時間來審查這些格式問題。
Git hooks 分為使用者端勾點和伺服器端勾點。使用者端勾點由諸如提交和合並這樣的操作所呼叫,而伺服器端勾點作用於諸如接收被推播的提交這樣的聯網操作。
使用者端勾點:pre-commit
、prepare-commit-msg
、commit-msg
、post-commit
等,主要用於控制使用者端 git 的提交和合並這樣的操作。
伺服器端勾點:pre-receive
、post-receive
、update
,主要在伺服器端接收提交物件時、推播到伺服器之前呼叫。
Git Hooks 就是在.git/hooks
檔案下,儲存了一些 shell 指令碼,然後在對應的勾點中執行這些指令碼就行了。比如下圖中,這是一個還沒有設定 Git Hooks 的倉庫,預設會有很.sample結尾的檔案,這些都是範例檔案
例如開啟pre-commit.sample
檔案看一下其中的內容,意思是一個範例勾點指令碼,用於驗證將要提交的內容,由沒有引數的「git commit」呼叫,如果勾點想要停止提交,那麼它應該在發出適當的訊息後以非零狀態退出。這個指令碼預設是不生效的,如果要生效,把檔名改為pre-commit
即可。pre-commit
這個勾點是在git commit
命令執行之前觸發。
Git 支援的所有勾點見下表(加粗的為常用勾點):
任何正確命名的可執行指令碼都可以正常使用 ,也可以用Ruby或Python,或其他指令碼語言。如下我們編寫一個與prepare-commit-msg相同命名的python指令碼即可,注意第一行改成了python直譯器的路徑。
#!/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!")
此外,這裡用sys.argv[1]
而不是$1來獲取第一個引數。這個特性非常強大,因為你可以用任何你喜歡的語言來編寫Git勾點。
使用shell 這裡嘗試寫一個簡單的勾點,安裝一個prepare-commit-msg勾點。去掉指令碼的.sample拓展名,在檔案中加上下面這兩行:
#!/bin/sh echo "# Please include a useful commit message!" > $1
接下來你每次執行git commit時,你會看到預設的提交資訊都被替換了。
內建的樣例指令碼是非常有用的參考資料,因為每個勾點傳入的引數都有非常詳細的說明(不同勾點不一樣)。
因為hook檔案其實就是個指令碼檔案,我們可以寫一個指令碼檔案到專案被git管理的任意目錄裡即可,只要在.git/hooks/裡的預設指令碼檔案中,執行我們外部的這個檔案即可。
/githooks/commit-msg-impl.py
#!/usr/bin/env python import sys, os, re from subprocess import check_output # 收集引數,第一個引數是commit的資訊的檔案 commit_msg_filepath = sys.argv[1] # 開啟commit提交訊息的檔案,檢測訊息是否以指定格式開頭的,不是則異常退出,終止這次commit訊息的提交 with open(commit_msg_filepath, 'r') as f: content = f.read() if not content.startswith("xxxx"): print "commit-msg: ERROR! The commit message must start with xxxx" sys.exit(1) - 預設hooks檔案:.git/hooks/commit-msg #!/bin/bash GIT_ROOT="$(git rev-parse --show-toplevel)" FILE_NAME=$GIT_ROOT/githooks/commit-msg-impl.py if [ -f "$FILE_NAME" ]; then source $FILE_NAME fi
從上面的介紹中,我們知道 Git Hook 儲存在 .git 資料夾中,Git 是一個多人共同作業工具,那按理說 Git 倉庫中的所有檔案都應該被跟蹤並且上傳至遠端倉庫的。但有個例外,.git資料夾不會,這就導致一個問題,我們在本地設定好 Git Hook 後,怎麼分享給其他小夥伴兒呢?這時候,就輪到 Husky 出場了。
Husky 的原理是讓我們在專案根目錄中寫一個組態檔,然後在安裝 Husky的時候把組態檔和 Git Hook 關聯起來,這樣我們就能在團隊中使用 Git Hook 了。
使用 npm 初始化你的專案(如果專案已有 package.json,請跳至第二步)
npm init -y
安裝 Husky
// 注意 Node.js 版本要 >=10 npm install husky -D
書寫組態檔,4.2.5 版本的 Husky 共支援以下幾種格式的組態檔:
.huskyrc
,在其中書寫 json 格式的設定,如下:{ "hooks": { "pre-commit": "git restore -W -S dist examples/dist" } }
是不是很簡單,我們來解讀一下這個組態檔。hooks這個物件中,key 就是勾點名,而 value 就是需要執行的命令。上面這個設定的含義就是,在每次執行 git commit
之前,都會把dist和examples/dit
目錄下的修改回滾,即不想這個目錄的檔案被上傳。
上面我們只寫了一條命令,如果想執行兩條命令怎麼辦呢?比如我還想在git commit
之前用 EsLint 檢查一下程式碼品質,我們可以像下面這樣寫:
{ "hooks": { "pre-commit": "git restore -W -S dist examples/dist && eslint ." } }
是的,就是這麼簡單。如果 EsLint 檢測不通過,那麼git commit是會被阻止的,就不用擔心"垃圾程式碼"被提交到線上倉庫了。
Husky 讓我們可以很方便的設定 Git Hooks,同時,也提供了一些實用方便的小技巧以及一些我們需要注意的點
Husky 不支援伺服器端 Git 的勾點:
HUSKY_SKIP_HOOKS=1 git rebase ...
如果你不想 Husky 為你自動安裝勾點(比如 clone 了一個第三方的庫,想要自己開發時),可以這樣做:
HUSKY_SKIP_INSTALL=1 npm install
推薦學習:《》
以上就是深入瞭解Git Hooks的使用的詳細內容,更多請關注TW511.COM其它相關文章!