当前位置: 首页 > news >正文

Git hook pre-commit

文章目录

    • Git hook
      • Git Hook 的核心功能
      • Git Hook 的分类
        • 客户端钩子(Client-side Hooks)
        • 服务端钩子(Server-side Hooks)
      • 典型应用场景
        • 提交前检查
        • 规范提交信息
        • 禁止推送敏感信息
        • 自动部署(服务端 post-receive)
      • 如何使用 Git Hooks?
        • 默认位置
        • 自定义目录(推荐团队协作)
      • 总结
    • Git pre-commit
      • `pre-commit` 钩子的核心作用
        • 自动化质量检查
        • 自动修复(可选)
      • 关于 `.githooks/` 目录
        • `pre-commit` 脚本示例
        • 注意事项

Git hook

  • Git Hooks(Git 钩子)是 Git 提供的一种强大机制,允许你在 Git 操作的特定关键节点自动执行自定义脚本。这些脚本可以用于自动化检查、验证、通知、部署等任务,从而提升开发效率、保障代码质量、加强协作规范。

Git Hook 的核心功能

功能类别说明
自动化检查在提交、推送前自动运行测试、代码风格检查、安全扫描等
质量保障阻止不符合规范的代码进入仓库(如含敏感信息、未通过测试)
流程控制强制执行团队约定(如提交信息格式、分支命名规则)
自动修复自动格式化代码、修复简单问题(如 Prettier、ESLint --fix)
通知与日志提交后发邮件、记录日志、触发 CI/CD 等
环境准备/清理在操作前后设置或清理临时文件、依赖等

Git Hook 的分类

Git Hooks 分为两大类:

客户端钩子(Client-side Hooks)

运行在开发者本地机器上,影响个人操作。

钩子名称触发时机常见用途
pre-commitgit commit 之前代码检查、格式化、测试
prepare-commit-msg默认提交信息生成后、编辑器打开前自动生成提交模板
commit-msg提交信息确定后、提交完成前校验提交信息格式(如符合 Conventional Commits)
post-commit提交完成后发通知、记录日志
pre-pushgit push 之前运行完整测试套件、检查是否遗漏文件
post-checkout / post-merge切换分支或合并后重新安装依赖、清理缓存

客户端钩子不会随仓库自动生效,需开发者手动启用(如配置 core.hooksPath 或使用工具如 Husky)。

服务端钩子(Server-side Hooks)

运行在远程 Git 服务器(如自建 Git 服务器、GitLab、Gitea),用于控制接收推送的行为。

钩子名称触发时机常见用途
pre-receive接收到推送请求、但未写入 refs 前全局检查(如禁止 force push、扫描恶意代码)
update对每个被推送的分支/标签单独检查细粒度权限控制(如只允许特定人推送到 main)
post-receive推送完成后自动部署、发 webhook、通知团队

GitHub/GitLab 等托管平台不支持自定义服务端钩子,但提供 WebhooksProtected Branches 等替代方案。

典型应用场景

提交前检查
# pre-commit
npm run lint && npm run test:unit

阻止有语法错误或测试失败的代码提交。

规范提交信息
# commit-msg
if ! head -n1 "$1" | grep -qE '^(feat|fix|docs|style|refactor|test|chore)(\(.+\))?: .+'; thenecho "Commit message must follow Conventional Commits format!"exit 1
fi
禁止推送敏感信息
# pre-push
if git diff origin/main..HEAD | grep -i "password\|secret\|token"; thenecho "🚫 检测到敏感词!禁止推送!"exit 1
fi
自动部署(服务端 post-receive)
#!/bin/bash
cd /var/www/myapp
git --git-dir=/var/repo/myapp.git --work-tree=/var/www/myapp checkout -f
npm install && pm2 reload app

如何使用 Git Hooks?

默认位置
.git/hooks/

包含 .sample 示例文件(如 pre-commit.sample),去掉后缀并赋予执行权限即可启用。

自定义目录(推荐团队协作)
# 将钩子放在项目内(如 .githooks/)
git config core.hooksPath .githooks

注意:

  • 钩子脚本必须有 可执行权限chmod +x
  • 客户端钩子 不会自动在 clone 后生效,需文档或脚本引导设置
  • 钩子不能被 Git 跟踪(除非你用 core.hooksPath 指向项目内目录)
  • 不要在钩子中做耗时过长的操作(会影响开发者体验)

总结

Git Hooks = Git 操作生命周期中的“自动化守门员”
它们让你在代码进入仓库的每一步都能自动执行检查、修复或通知,是构建高质量、规范化开发流程的关键工具。

如果你有具体需求(比如“如何在提交前自动格式化 Python 代码”),欢迎告诉我,我可以给出完整配置示例!

Git pre-commit

在 Git 中,.githooks/pre-commit(更准确地说,是 被配置为钩子目录的 .githooks/ 中的 pre-commit 脚本)的核心功能是:在每次执行 git commit 命令、但尚未真正创建提交之前,自动运行一段自定义脚本,用于检查或处理即将提交的代码

pre-commit 钩子的核心作用

  • 如果 pre-commit 脚本以 非零状态退出(例如 exit 1),Git 会 中止本次提交
  • 如果脚本成功退出(exit 0 或正常结束),提交继续进行。
自动化质量检查

在代码进入版本历史前,自动执行:

  • 代码风格检查(如 ESLint、Prettier)
  • 静态类型检查(如 TypeScript 的 tsc --noEmit
  • 单元测试运行
  • 禁止提交调试代码(如 console.logdebugger
  • 检查敏感信息(如密码、密钥)是否误提交
自动修复(可选)
  • 有些工具(如 Prettier)可以在 pre-commit 中自动格式化暂存区的文件,并重新 git add,实现“提交前自动美化代码”。

关于 .githooks/ 目录

  • Git 默认的钩子目录是 .git/hooks/,但该目录 不会被 Git 跟踪(无法共享给团队)。

  • 为了便于协作,很多项目将钩子脚本放在项目根目录下的 .githooks/(或其他名称如 .git-hooks/)中,并通过以下命令启用:

    git config core.hooksPath .githooks
    
  • 设置后,Git 会从 .githooks/ 而不是 .git/hooks/ 加载钩子脚本。

  • .githooks/ 可以加入版本控制(git add .githooks),实现团队共享。

pre-commit 脚本示例
#!/bin/bash
#
# Pre-commit hook - Google C++ 代码风格检查
# 功能:检查代码风格,生成期望代码,用meld比较(左侧当前,右侧期望)
## 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'# 临时文件目录
TEMP_DIR="/tmp/git-precommit-$$"
mkdir -p "$TEMP_DIR"
trap "rm -rf $TEMP_DIR" EXIT# 获取要检查的提交基准
if git rev-parse --verify HEAD >/dev/null 2>&1; thenagainst=HEAD
elseagainst=$(git hash-object -t tree /dev/null)
fiexec 1>&2echo -e "${BLUE}=== C++ 代码风格检查 ===${NC}"# 代码风格修复函数
fix_style() {local file="$1"local has_issues=falselocal fixed_content=""local prev_line=""while IFS= read -r line; dooriginal_line="$line"fixed_line="$line"# 1. 流操作符空格: << (包括LOG) - 确保前后都有空格if echo "$line" | grep -q '<<'; then# 先处理 << 前面没有空格的情况fixed_line=$(echo "$fixed_line" | sed -E 's/([^[:space:]<])<<([[:space:]]|[^[:space:]<])/\1 << \2/g')# 再处理 << 后面没有空格的情况(但不是 <<< 或更多的<)fixed_line=$(echo "$fixed_line" | sed -E 's/<<([^[:space:]<])/<< \1/g')fi# 2. 赋值操作符空格: a=b -> a = bif echo "$line" | grep -qE '[^[:space:]!<>=]=[^[:space:]=]' && ! echo "$line" | grep -qE '==|!=|<=|>='; thenfixed_line=$(echo "$fixed_line" | sed -E 's/([^[:space:]!<>=])=([^[:space:]=])/\1 = \2/g')fi# 3. 比较和逻辑操作符空格: ==, !=, &&, ||if echo "$original_line" | grep -qE '[^[:space:]]==[^[:space:]]|[^[:space:]]!=[^[:space:]]|[^[:space:]]&&[^[:space:]]|[^[:space:]]\|\|[^[:space:]]'; thenfixed_line=$(echo "$fixed_line" | sed -E 's/([a-zA-Z0-9_])==([a-zA-Z0-9_])/\1 == \2/g;s/([a-zA-Z0-9_])!=([a-zA-Z0-9_])/\1 != \2/g;s/([a-zA-Z0-9_])&&([a-zA-Z0-9_])/\1 \&\& \2/g;s/([a-zA-Z0-9_])\|\|([a-zA-Z0-9_])/\1 || \2/g')fi# 4. 逗号后空格: a,b -> a, bif echo "$line" | grep -qE ',[^[:space:]]' && ! echo "$line" | grep -q '".*,.*"'; thenfixed_line=$(echo "$fixed_line" | sed -E 's/,([^[:space:]])/, \1/g')fi# 5. 删除代码块开头的空行local skip_line=falseif [ -n "$prev_line" ] && echo "$prev_line" | grep -qE '\{[[:space:]]*$'; thenif [ -z "$(echo "$line" | sed 's/[[:space:]]//g')" ]; thenskip_line=truehas_issues=truefifi# 检测是否有修改if [ "$original_line" != "$fixed_line" ]; thenhas_issues=truefi# 添加到修复内容(跳过多余空行)if [ "$skip_line" != true ]; thenfixed_content+="$fixed_line"$'\n'fiprev_line="$original_line"done < "$file"if [ "$has_issues" = true ]; thenecho -n "$fixed_content" > "$TEMP_DIR/$(basename "$file").expected"echo "$TEMP_DIR/$(basename "$file").expected"return 1fireturn 0
}# 检测交互式环境
is_interactive() {if [ -w /dev/tty ] 2>/dev/null; thenreturn 0elif [ -t 1 ] || [ -t 2 ]; thenreturn 0elif [ -n "$TERM" ] && [ "$TERM" != "dumb" ] && [ -z "$CI" ] && [ -z "$GITHUB_ACTIONS" ]; thenreturn 0fireturn 1
}# 获取本次提交的C++文件
cpp_files=$(git diff --cached --name-only --diff-filter=ACM $against | grep -E '\.(cpp|cc|cxx|c\+\+|h|hpp|hxx|h\+\+)$' || true)if [ -z "$cpp_files" ]; thenecho -e "${GREEN}没有C++文件需要检查${NC}"exit 0
fi# 检查每个文件
has_style_issues=false
files_to_compare=()while IFS= read -r file; doif [ ! -f "$file" ]; thencontinuefiecho -e "检查: ${BLUE}$file${NC}"expected_file=$(fix_style "$file")if [ $? -ne 0 ]; then# fix_style返回1表示有格式问题has_style_issues=truefiles_to_compare+=("$file:$expected_file")echo -e "  ${YELLOW}✗ 发现格式问题${NC}"elseecho -e "  ${GREEN}✓ 格式正确${NC}"fi
done <<< "$cpp_files"# 如果有格式问题
if [ "$has_style_issues" = true ]; thenechoecho -e "${RED}发现代码风格问题!${NC}"# 判断是否为交互式环境if ! is_interactive; thenecho -e "${YELLOW}非交互式环境,取消提交${NC}"exit 1fi# 检查meld是否安装if ! command -v meld >/dev/null 2>&1; thenecho -e "${RED}未安装 meld 工具${NC}"echo "安装: sudo apt-get install meld"exit 1fi# 使用meld比较每个文件for file_pair in "${files_to_compare[@]}"; docurrent_file="${file_pair%%:*}"expected_file="${file_pair##*:}"echoecho -e "${BLUE}=====================================${NC}"echo -e "${BLUE}文件: $current_file${NC}"echo -e "${GREEN}左侧 = 当前代码${NC}"echo -e "${YELLOW}右侧 = 期望代码${NC}"echo -e "${BLUE}=====================================${NC}"echo -e "${YELLOW}请在meld中查看差异,关闭meld窗口后继续...${NC}"echo# 启动meld(左侧当前,右侧期望)- 前台运行,等待用户关闭meld "$current_file" "$expected_file" 2>/dev/nullecho -e "${GREEN}meld已关闭${NC}"# 询问是否应用修改echo -ne "${YELLOW}应用期望代码到当前文件?(y/N) ${NC}"read -r applyif [[ "$apply" =~ ^[Yy]$ ]]; thencp "$current_file" "$current_file.backup"cp "$expected_file" "$current_file"git add "$current_file"echo -e "${GREEN}✓ 已应用并添加到暂存区${NC}"echo -e "${GREEN}  备份: $current_file.backup${NC}"elseecho -e "${YELLOW}跳过此文件${NC}"fidoneechoecho -ne "${YELLOW}是否继续提交?(y/N) ${NC}"read -r continue_commitif [[ ! "$continue_commit" =~ ^[Yy]$ ]]; thenecho -e "${RED}提交已取消${NC}"exit 1fi
fiecho -e "${GREEN}=== 检查通过 ===${NC}"
exit 0
注意事项
  • 钩子脚本必须有 可执行权限chmod +x .githooks/pre-commit
  • 钩子 不会自动在克隆仓库后生效,需团队成员手动运行 git config core.hooksPath .githooks(可通过 README 或初始化脚本引导)
  • 更推荐使用专业工具管理钩子,如:
    • Husky(Node.js 项目)
    • pre-commit(多语言支持,通过 YAML 配置)
http://www.dtcms.com/a/566077.html

相关文章:

  • 展示系统 网站模板广西新闻
  • Java基础语言进阶学习——2,对象创建机制与内存布局
  • 网站seo啥意思怎么做罗田县建设局网站
  • 基于yolov8的果蔬识别检测系统python源码+onnx模型+数据集+精美GUI界面
  • 网站建设合同电子版苏州网页制作报价
  • 廊坊网站建设方案策划民治做网站
  • 走路摆臂幅度大给人影响差-----坏习惯
  • TRO重磅消息 野生动物插画师Roger Hall跨境维权风暴来袭
  • ABB焊接机器人节气装置
  • Linux 孤儿进程和僵尸进程详解
  • jsp做网站用什么封装字符串餐饮加盟什么网站建设
  • 做网站挂谷歌广告赚钱吗电子商务网站模板html
  • 基于 OpenVINO 实现 SpeechT5 语音合成模型本地部署加速
  • 北京市建设工程审核在哪个网站打车软件app开发
  • 怎么做站旅游网站上泡到妞主流网站宽度
  • 【底层机制】解析Espresso测试框架的核心原理
  • 网站如何做中英文效果wordpress主题开发培训
  • PostIn零基础学习 - 快速对接口进行调试
  • 网站建设沛宣北京vi设计公司哪
  • 高明网站建设报价品牌网站建设创意新颖
  • HTML DOM outerHTML 属性
  • SpringBoot 登录验证码
  • Spring Al Alibaba
  • 陕西民盛建设有限公司网站pageadmin的最新版本
  • 如何自己做个网站网站xml
  • 易语言怎么制作网站临淄辛店今天招聘信息
  • 相亲网站源码php模版营销网站的概念
  • css文档流
  • C#进阶11:C#局部路径规划算法_DWA
  • 基于Vue人脸识别的智慧课堂学习行为分析系统f36fy939(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。