WEBKT

别再乱写 Commit 了!利用 Git commit-msg 钩子与正则实现自动化规范校验

3 0 0 0

在团队协作中,混乱的 Git 提交信息(Commit Message)是后期维护的灾难。你是否见过满屏的 updatefix 甚至是 ...?这不仅让 git log 失去了追踪意义,更导致自动化生成 Changelog 变得不可能。

目前业界公认的最佳实践是 Conventional Commits(约定式提交)。本文将深入探讨如何利用 Git 自带的 commit-msg 钩子,配合正则表达式,在代码提交的第一道关口实现强制规范校验。

1. 什么是 Conventional Commits?

约定式提交规范提供了一个轻量级的提交历史结构。其核心格式如下:

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]
  • feat: 新功能
  • fix: 修补错误
  • docs: 文档改变
  • style: 代码格式改变(不影响代码运行的变动)
  • refactor: 重构(既不是新增功能,也不是修改 bug 的代码变动)
  • perf: 性能优化
  • test: 增加测试
  • chore: 构建过程或辅助工具的变动

2. Git 钩子机制:commit-msg

Git Hooks 是 Git 在特定事件发生时触发的脚本。其中 commit-msg 钩子在用户输入提交信息并保存后触发。

  • 触发时机:在编辑器关闭、提交信息存入临时文件之后。
  • 输入参数:该钩子接收一个参数,即保存提交信息的临时文件路径
  • 拦截机制:如果脚本以非零状态码退出(exit 1),Git 将放弃此次提交。

3. 构建核心正则表达式

要校验提交信息,我们需要一个能够覆盖规范且严谨的正则。

推荐使用的正则:

/^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?!?: .+/

解析:

  1. ^: 匹配行首。
  2. (feat|fix|...): 必须以这些指定的 type 开头。
  3. (\(.+\))?: 可选的作用域(scope),包裹在圆括号内。
  4. !?: 可选的惊叹号,表示包含破坏性变更(Breaking Change)。
  5. : : 必须包含冒号加空格。
  6. .+: 后面必须跟上具体的描述信息。

4. 编写 commit-msg 钩子脚本

在你的项目根目录下,找到 .git/hooks/commit-msg.sample,将其重命名为 commit-msg(去掉后缀),并写入以下代码:

#!/bin/sh

# 获取提交信息文件的路径
COMMIT_MSG_FILE=$1
# 读取提交信息的第一行
COMMIT_MSG=$(head -n 1 "$COMMIT_MSG_FILE")

# 定义正则规范
REGEXP="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?!?: .+"

# 检查是否匹配正则
if ! echo "$COMMIT_MSG" | grep -Eq "$REGEXP"; then
    echo "  "
    echo "Error: 不符合规范的提交格式!"
    echo "  "
    echo "正确格式: <type>(scope?): <description>"
    echo "例如: feat(auth): 增加用户登录功能"
    echo "      fix: 修复内存泄漏问题"
    echo "  "
    echo "常见 type 包括: feat, fix, docs, style, refactor, perf, test, chore, revert"
    echo "请修改后重新提交。"
    exit 1
fi

关键步骤:必须赋予脚本可执行权限:

chmod +x .git/hooks/commit-msg

5. 进阶:如何让全团队共享钩子?

.git 文件夹下的内容不会被提交到远程仓库。为了让团队成员都强制执行此规范,有几种常见方案:

方案 A:使用 Husky (推荐用于 Node.js 项目)

Husky 是前端领域最流行的工具,它可以将钩子配置存储在 package.json 中,并在 npm install 时自动安装到本地 .git/hooks

npx husky-init && npm install
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'

方案 B:配置 git config core.hooksPath

你可以创建一个自定义的目录(如 .githooks),将脚本放入其中并提交。然后让团队成员执行:

git config core.hooksPath .githooks

6. 为什么不直接使用 commitlint?

市面上确实有成熟的工具如 @commitlint/cli。如果你追求开箱即用,它们是首选。但深入理解 commit-msg 钩子和正则的意义在于:

  1. 轻量化:无需安装成百上千的 node_modules,仅靠几行 Shell 脚本即可实现。
  2. 高度自定义:你可以根据公司内部标准,自定义特定的 type(比如公司内部的单号格式 PROJ-123: fix something)。
  3. 多语言通用:无论你的项目是 Go、Python 还是 C++,Shell 脚本钩子是通用的。

总结

自动化规范校验是 DevOps 的第一步。通过简单的 commit-msg 钩子,我们可以确保 Git 历史记录的整洁与可读。这不仅方便了开发者自己回溯代码,更为后续的自动化发布、版本号自动演进(Semantic Versioning)打下了坚实的基础。

现在,去给你的项目加上这个“紧箍咒”吧!

码农架构师 Git Hooks正则表达式代码规范

评论点评