git hook

简介: Hook 机制 用于拦截、修改或扩展程序的行为。通过 Hook 机制,程序可以在不修改源代码或核心逻辑的情况下,向特定的事件、函数调用之前或之后插入自定义代码。Hook 机制通常被用于调试、监控、拦截系统调用、修改程序的行为等场景。

客户端钩子

在本地 Git 仓库操作中执行的钩子脚本,允许开发者在特定的 Git 操作发生时插入自定义逻辑。客户端钩子通常在开发者本地执行,作用于个人开发环境中,用于处理一些如代码格式化、验证、提交前检查等任务,客户端的钩子种类优先,详见:.git/hooks。

类别

钩子名称

触发时机

用途

提交

commit-msg

git commit 提交信息生成后

验证 commit msg

prepare-commit-msg

git commit 提交信息生成前

修改或生成提交信息

pre-commit

git commit 执行前

执行代码检查、格式化等

推送

pre-push

git push 执行前

推送前检查

pre-receive

常用于远程仓库接收推送时

服务端验证推送的内容

合并

pre-merge-commit

执行合并提交之前

合并操作前执行检查或自动化任务

pre-rebase

git rebase 之前

变基操作前执行检查

补丁

applypatch-msg

应用补丁时

检查补丁的提交信息

pre-applypatch

应用补丁前

检查补丁的内容

post-update

远程仓库更新后,常用于服务器端

触发远程仓库更新后的任务

其他

sendemail-validate

git send-email 发送邮件时

检查和验证发送邮件的内容。

push-to-checkout

远程仓库更新时

远程仓库更新时触发的操作

update

git update-server-info 执行时

更新仓库的内部信息或触发通知

使用事例

git commit msg 校验

#!/bin/bash
commit_msg=$(cat "$1")
commit_regex="^(feat|fix|refactor|docs|style|test|chore|perf|ci|build|revert|wip) \[JIRA-[0-9]+\] : .+"
if ! echo "$commit_msg" | grep -qE "$commit_regex"; then
        echo "ERROR: Invaild commit message format, example:" >&2
        echo "refactor [JIRA-1234] : commit message"
        echo ""
        echo "feat:      引入新功能"
        echo "fix:       修复bug或错误"
        echo "refactor:  对代码进行重构,但不改变外部行为"
        echo "docs:      更新文档(如 README、API 文档等)"
        echo "style:     修改代码格式(如缩进、空格、分号等), 不改变功能"
        echo "test:      添加或修改测试代码"
        echo "chore:     更新构建工具、依赖或其他不影响应用功能的任务"
        echo "perf:      提高性能的修改"
        echo "build:     修改构建系统或外部依赖"
        echo "revert:    撤销某个提交的提交"
        echo "ci:        修改 CI 配置或脚本"
        echo "wip:       标记为工作进行中的提交"
        exit 1
else
        echo "INFO: $commit_msg"
fi
exit 0
# ubuntu @ ubuntu in ~/Code/leetcode on git:master x [13:17:38]
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   commit_msg.txt
# ubuntu @ ubuntu in ~/Code/leetcode on git:master x [13:17:41]
$ git commit -m "commit invaild format msg"
ERROR: Invaild commit message format, example:
refactor [JIRA-1234] : commit message
feat:      引入新功能
fix:       修复bug或错误
refactor:  对代码进行重构,但不改变外部行为
docs:      更新文档(如 README、API 文档等)
style:     修改代码格式(如缩进、空格、分号等), 不改变功能
test:      添加或修改测试代码
chore:     更新构建工具、依赖或其他不影响应用功能的任务
perf:      提高性能的修改
build:     修改构建系统或外部依赖
revert:    撤销某个提交的提交
ci:        修改 CI 配置或脚本
wip:       标记为工作进行中的提交
# ubuntu @ ubuntu in ~/Code/leetcode on git:master x [13:17:46] C:1
$ git commit -m "feat [JIRA-1234] : add new file"
INFO: feat [JIRA-1234] : add new file
[master d1eff26] feat [JIRA-1234] : add new file
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 commit_msg.txt
# ubuntu @ ubuntu in ~/Code/leetcode on git:master o [13:18:14]
$

git push 编译校验

#!/bin/bash
echo "Running pre-push hook... Compiling the code before push..."
if ! ( cmake -S . -B build && cmake --build build ) ; then
    echo "ERROR: Compilation failed! Push aborted."
    exit 1
else
    echo "INFO: Compilation successful. Proceeding with push."
fi
# 无法通过编译push失败
# ubuntu @ ubuntu in ~/Code/leetcode on git:main o [14:35:16] 
$ git push                                      
INFO: Running pre-push hook... Compiling the code before push...
-- install: /home/ubuntu/Code/leetcode/app
-- Using GNU compiler
-- Using -std=c++20
-- GTest version: 1.14.0
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/ubuntu/Code/leetcode/build
[ 50%] Building CXX object src/CMakeFiles/x_exec.dir/x.cc.o
/home/ubuntu/Code/leetcode/src/x.cc: In function ‘int main()’:
/home/ubuntu/Code/leetcode/src/x.cc:7:11: error: expected ‘;’ before ‘}’ token
    7 |   return 0
      |           ^
      |           ;
    8 | }
      | ~          
gmake[2]: *** [src/CMakeFiles/x_exec.dir/build.make:76: src/CMakeFiles/x_exec.dir/x.cc.o] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:98: src/CMakeFiles/x_exec.dir/all] Error 2
gmake: *** [Makefile:101: all] Error 2
ERROR: Compilation failed! Push aborted.
error: failed to push some refs to 'github.com:croquettess/leetcode.git'
# 仅可通过编译时push成功
# ubuntu @ ubuntu in ~/Code/leetcode on git:main o [14:19:46] 
$ git push                                      
INFO: Running pre-push hook... Compiling the code before push...
-- install: /home/ubuntu/Code/leetcode/app
-- Using GNU compiler
-- Using -std=c++20
-- GTest version: 1.14.0
-- Configuring done (0.1s)
-- Generating done (0.0s)
-- Build files have been written to: /home/ubuntu/Code/leetcode/build
[ 50%] Building CXX object src/CMakeFiles/x_exec.dir/x.cc.o
[100%] Linking CXX executable x_exec
[100%] Built target x_exec
INFO: Compilation successful. Proceeding with push.
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 4 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (8/8), 742 bytes | 742.00 KiB/s, done.
Total 8 (delta 4), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (4/4), completed with 2 local objects.
To github.com:croquettess/leetcode.git
   0920c24..d38da12  main -> main

使用限制

  1. 无法共享:钩子仅在本地有效,无法自动同步到团队成员,需要手动配置。
  2. 跨平台兼容性:钩子脚本通常是 Shell 脚本,在不同操作系统上可能无法兼容。
  3. 性能问题:一些钩子执行复杂操作可能影响 Git 操作速度。
  4. 容易绕过:开发者可以禁用本地钩子,导致一些强制操作被绕过。
  5. 无法控制全局设置:钩子仅对单个仓库有效,无法在多个仓库中共享,需要手动配置或使用统一管理工具。

服务端钩子

Git 仓库在特定事件发生时,通过 HTTP POST 请求通知外部服务器。,例如 CI/CD、代码检查等。当 Git 仓库中的代码发生变化(如提交、推送、拉取请求等),Webhook 会自动触发并将相关信息发送到指定的 URL。分发 hook

hook 类型:github->repository->Settings->webhooks->Add webhook->Let me select individual events.

使用事例

jenkins 自动集成

通过 webhook 配置,向 main 分支提交代码后,jenkins 自动集成

  1. jenkins:
  1. 新增/选择一个任务->配置
  2. 源码管理
  1. Git:
    Repository URL: 项目地址
    Branches to build: */main
    Triggers: 选择 GitHub hook trigger for GITScm pollin
  2. Triggers:
    选择 GitHub hook trigger for GITScm polling
  3. Build Steps
    执行 shell:添加构建、编译命令g
  1. github 添加钩子
  1. github->repository->Settings->webhooks->Add webhook
  2. Payload URL: http://$jenkins_endpoint//github-webhook/
  3. Content type: application/json
  4. Which events would you like to tragger this webhook?: Just the push event.
  5. Add webhook
  1. 更新提交到 main 分支
# ubuntu @ ubuntu in ~/Code/leetcode on git:main x [16:33:02] 
$ git add .   
# ubuntu @ ubuntu in ~/Code/leetcode on git:main x [16:33:06] 
$ git commit -m "feat [JIRA-0000] : jenkins auto build"
INFO: feat [JIRA-0000] : jenkins auto build
[main 112b6d5] feat [JIRA-0000] : jenkins auto build
 1 file changed, 1 insertion(+), 1 deletion(-)
# ubuntu @ ubuntu in ~/Code/leetcode on git:main o [16:33:10] 
$ git push                                             
INFO: Running pre-push hook... Compiling the code before push...
-- install: /home/ubuntu/Code/leetcode/app
-- Using GNU compiler
-- Using -std=c++20
-- GTest version: 1.14.0
-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/ubuntu/Code/leetcode/build
[ 50%] Building CXX object src/CMakeFiles/x_exec.dir/x.cc.o
[100%] Linking CXX executable x_exec
[100%] Built target x_exec
INFO: Compilation successful. Proceeding with push.
Enumerating objects: 15, done.
Counting objects: 100% (15/15), done.
Delta compression using up to 4 threads
Compressing objects: 100% (12/12), done.
Writing objects: 100% (12/12), 1.14 KiB | 1.14 MiB/s, done.
Total 12 (delta 5), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (5/5), completed with 2 local objects.
To github.com:croquettess/leetcode.git
   d38da12..112b6d5  main -> main
# ubuntu @ ubuntu in ~/Code/leetcode on git:main o [16:33:17] 
$
  1. 查看 jenkins 控制台
  2. 运行
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/var/lib/jenkins/workspace/webhook/build/src » ./x_exec                                                                                                                ubuntu@VM-16-13-ubuntu
jenkins auto build new
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/var/lib/jenkins/workspace/webhook/build/src »                                                                                                                         ubuntu@VM-16-13-ubuntu

自定义 webhook

需要编写可以与 git 服务器建立连接的 http 服务器,处理 github 的 webhook

  1. 编写 http 服务器
import logging                                                                                                                                                                                
from flask import Flask, request, jsonify
import hmac
import hashlib
import json
app = Flask(__name__)
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger()
# 配置 GitHub Secret 密钥
GITHUB_SECRET = "webhook"
# 用于验证签名
def verify_signature(payload, signature):
    mac = hmac.new(GITHUB_SECRET.encode(), msg=payload, digestmod=hashlib.sha256)
    return hmac.compare_digest("sha256=" + mac.hexdigest(), signature)
# 处理 webhook
@app.route('/my-webhook', methods=['POST'])
def github_webhook():
    if request.method == 'POST':
        logger.info("Received POST request")
        signature = request.headers.get('X-Hub-Signature-256')
        payload = request.data
        # 验证签名
        if not verify_signature(payload, signature):
            logger.error("Invalid signature")
            return "Invalid signature", 400 
        try:
            data = json.loads(payload)
            logger.info(f"Received GitHub payload: {json.dumps(data, indent=2)}")
        except json.JSONDecodeError:
            logger.error("Invalid JSON in payload")
            return "Invalid JSON", 400 
        # 处理 push 事件
        if data.get('action') == 'push':
            logger.info("A push event occurred")
            logger.info(f"Push to branch: {data['ref']}")
        return jsonify({"status": "success"}), 200 
    else:
        return "Method Not Allowed", 405
if __name__ == '__main__':
    app.run(host='0.0.0.0', port=10000, debug=True)
  1. 启动 nohup python3 webhook.py &
  2. github 添加名称为 my-webhook 的钩子,步骤详见:服务端钩子/jenkins 自动集成/github 添加钩子
  3. 修改项目代码后 push 到 git 服务器上,查看 webhook 服务器日志
~ » cat nohup.out                                                                                                                                                      ubuntu@VM-16-13-ubuntu
 * Serving Flask app 'webhook'
 * Debug mode: on
2024-12-28 21:23:53,248 - INFO - WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on all addresses (0.0.0.0)
 * Running on http://127.0.0.1:10000
 * Running on http://10.0.16.13:10000
2024-12-28 21:23:53,249 - INFO - Press CTRL+C to quit
2024-12-28 21:23:53,250 - INFO -  * Restarting with stat
2024-12-28 21:23:53,517 - WARNING -  * Debugger is active!
2024-12-28 21:23:53,520 - INFO -  * Debugger PIN: 108-869-862
2024-12-28 21:35:52,506 - INFO - Received POST request
2024-12-28 21:35:52,509 - INFO - Received GitHub payload: {
  "ref": "refs/heads/main",
  "before": "876a741cfd6ea55289187e80b82e61f8105632aa",
  "after": "63fce6d795246d80a3040984b7f3ee29a3e2b0bc",
......
}
2024-12-28 21:35:52,510 - INFO - 140.82.115.73 - - [28/Dec/2024 21:35:52] "POST /my-webhook HTTP/1.1" 200 -

使用限制

  1. 无法共享:每个 Webhook 配置独立,无法在多个项目间共享,需要手动配置。
  2. 速率限制:高频触发的事件可能被限流或延迟发送。
  3. 请求大小限制:单次请求的 Payload 数据大小有限(如 GitHub 最大 25 MB)。
  4. 重试机制有限:服务端失败返回后,Webhook 只会重试有限次数,重试用尽后事件可能丢失。
  5. 事件支持范围有限:仅支持特定事件类型,复杂触发逻辑需自行实现。
相关文章
|
项目管理 开发工具 git
git push 报错 pre-receive hook declined
git push 报错 pre-receive hook declined
4015 0
git push 报错 pre-receive hook declined
|
3月前
|
前端开发 开发工具 git
如何清理 docker 磁盘空间+修改 Gitea 服务器的 Webhook 设置+前端一些好学好用的代码规范-git hook+husky + commitlint
如何清理 docker 磁盘空间+修改 Gitea 服务器的 Webhook 设置+前端一些好学好用的代码规范-git hook+husky + commitlint
46 5
|
3月前
|
前端开发 开发工具 git
搭建Registry&Harbor私有仓库、Dockerfile(八)+前端一些好学好用的代码规范-git hook+husky + commitlint
搭建Registry&Harbor私有仓库、Dockerfile(八)+前端一些好学好用的代码规范-git hook+husky + commitlint
26 0
|
前端开发 开发工具 git
前端hook项目moblie总结笔记-忽略提交的git文件
前端hook项目moblie总结笔记-忽略提交的git文件
97 0
前端hook项目moblie总结笔记-忽略提交的git文件
|
前端开发 开发工具 git
前端hook项目moblie总结笔记-忽略提交的git文件
前端hook项目moblie总结笔记-忽略提交的git文件
93 0
前端hook项目moblie总结笔记-忽略提交的git文件
|
前端开发 开发工具 git
前端hook项目moblie总结笔记-git进行仓库初始化
前端hook项目moblie总结笔记-git进行仓库初始化
97 0
|
开发工具 git
Git - [remote rejected] master - master (pre-receive hook declined)
Git - [remote rejected] master - master (pre-receive hook declined)
889 0
Git - [remote rejected] master - master (pre-receive hook declined)
|
开发工具 git
git提交出现running pre-commit hook: lint-staged
git提交出现running pre-commit hook: lint-staged
git提交出现running pre-commit hook: lint-staged
|
小程序 JavaScript 前端开发
将CSScomb集成到Git Hook中
将CSScomb集成到Git Hook中
143 0
|
数据可视化 Shell 测试技术