Gitru:Rust打造的零依赖Git提交信息校验工具,如何实现疑问?

摘要:gitru 基于 Git 的 commit-msg Hook 实现,用于在提交阶段自动校验提交信息格式。 在团队协作开发中,规范的 Git 提交信息是代码追溯、版本管理、自动生成变更日志的基础。 但现实往往是: 人工约束容易遗漏 手动配置
gitru 基于 Git 的 commit-msg Hook 实现,用于在提交阶段自动校验提交信息格式。 在团队协作开发中,规范的 Git 提交信息是代码追溯、版本管理、自动生成变更日志的基础。 但现实往往是: 人工约束容易遗漏 手动配置 Hook 繁琐 提交信息格式随心所欲 生成 changelog 时异常痛苦 因此,必须由工具来保证提交信息的规范性。 市面上已有不少成熟工具,但大多基于 Node.js / Python / Shell 实现。问题是: 只是想校验一个字符串,却要先安装 Node 或 Python 版本不一致可能导致各种奇怪的问题 国内下载依赖速度慢甚至失败 安装一个工具可能要拉下一堆包 属于“操作一大堆,却还没开始进入正题”。 这些对普通开发者,尤其是新手,并不友好。 当然,这并不是否定这些工具。相反,它们非常优秀,本项目开发过程中也使用了著名的 pre-commit。与这些成熟工具相比,gitru 甚至连 hello-world 都算不上,只是一个更轻、更简单的选择。 基于以上考虑,再加上 Rust 非常适合编写 CLI 工具,于是就有了 gitru。 ✨ 项目特点 🦀 Rust 编写,零依赖二进制分发 下载即可运行,无需 Node、Python 或虚拟环境。 (虽然我不想把“Rust 编写”当成卖点,免得被误会成 Rust 传教士,但和其他成熟工具相比,这确实是 gitru 少数能拿得出手的特点之一。) ⚙️ TOML 格式自定义规则 简单、清晰、易读、易维护。 ⏭️ 支持通过关键字跳过校验 适用于自动化提交、紧急修复等场景。 🇨🇳 支持中文提交信息校验 不会误判中文标点,对中文开发者更友好。 🎨 错误信息带颜色输出 更直观、更易读。 🔍 支持 Footer 关键字拼写校验(Spell Check) 当提交信息疑似拼写错误时,gitru 会自动检测并给出友好提示,避免因拼写错误导致自动化流程失效。(当然,这部分依赖算法和用户配置,体验远不如当下的ai) 📘 Conventional Commits 简介 在介绍 gitru 的使用前,必须先了解业内广泛采用的提交规范 —— Conventional Commits。 它定义了提交信息的结构: <type>[optional scope]: <subject> [optional body] [optional footer(s)] 其中: type(必填):如 feat、fix,用于分类 scope(可选):如 core、ui,用于描述影响范围 !(可选):表示破坏性变更 subject(必填):简短描述本次变更 body(可选):详细说明 footer(可选):如 BREAKING CHANGE、Closes #123 gitru 就是基于此规范实现的,并允许你通过配置文件进行自定义。 📦 安装 gitru 你可以通过三种方式安装: 方式一:直接下载二进制文件(推荐) 前往👉 GitHub Releases 下载对应平台的压缩包,解压后: 放到任意目录 加入 PATH Linux / macOS 可能需要执行权限 方式二:通过 cargo 安装(需 Rust 环境) cargo install gitru 方式三:本地编译 git clone https://github.com/xiyixiaodao/gitru.git cd gitru cargo install --path . 验证安装: gitru --version 🛠 使用方法 一键初始化 以下命令会同时安装 Hook 并生成配置文件: gitru ii commit-msg 它等价于: gitru install commit-msg gitru init commit-msg 如果文件已存在,可强制覆盖: gitru ii commit-msg -f 卸载 Hook gitru uninstall commit-msg 然后手动删除 .commit-msg-rule.toml。 ⚙️ 自定义校验规则 gitru 的核心是配置文件 .commit-msg-rule.toml。 你只需要修改它,就能完全定制校验逻辑。 为什么选择 TOML 而不是 YAML? YAML 结构依赖缩进,容易错位 .yaml / .yml 后缀容易混淆 TOML 更简单、可读性更强 对新手更友好 即使你不懂 TOML,也完全不影响使用。 📄 配置文件示例 下面是 gitru 初始化后生成的配置文件(部分注释已去除): # ╔═════════════════════════════════════════════════╗ # ║ COMMIT FORMAT TEMPLATE ║ # ╠═════════════════════════════════════════════════╣ # ║ type(optional scope): subject ║ # ║ ║ # ║ [optional body] ║ # ║ ║ # ║ [optional footer] ║ # ║ - BREAKING CHANGE: xxxxx ║ # ║ - Closes #issue ║ # ╚═════════════════════════════════════════════════╝ [global] version = "1.0.0" enable_validation = true skip_validation_words = ["--no-verify", "SKIP"] [header.type] allowed_types = ["feat", "fix", "docs", "style", "refactor", "test", "chore", "ci"] [header.scope] required = false allowed_scopes = ["core", "cli", "ui", "docs", "test"] [header.subject] spaces_after_colon = 1 forbid_trailing_period = true min_length = 2 max_length = 72 [body] required = false min_blank_lines_before_body = 1 forbid_trailing_whitespace = true min_line_length = 2 max_line_length = 72 [footer] start_key_words = ["BREAKING CHANGE", "Closes", "Fixes", "Signed-off-by"] min_blank_lines_before_footer = 1 min_line_length = 2 max_line_length = 72 forbid_trailing_whitespace = true [footer.start_key_words_spellcheck] enable = true threshold = 0.7 🔍 配置项详解 下面对关键配置项进行说明(按模块划分)。 1. 全局配置(global) 控制 gitru 的整体行为: [global] version = "1.0.0" enable_validation = true skip_validation_words = ["--no-verify", "SKIP"] version: 用于以后大版本变更升级区分,当前没有区别。 enable_validation:是否启用校验 skip_validation_words:提交信息第一行完全匹配时跳过校验 2. Header 校验 Header 是最重要的部分,包含: type(scope): subject 2.1 type 校验 [header.type] allowed_types = ["feat", "fix", "docs", "style", "refactor", "test", "chore", "ci"] 避免出现 update、tmp、aaa 等无意义 type 让团队提交类型统一 让 changelog 自动生成更准确 ⚠ 不允许为空数组 若不需要 type 校验,请注释掉整个字段。 提交示例: 校验通过: feat: add login API 校验失败: #错误示例1 update: change UI layout #提示 error: commit type `update` is not in the allowed list, allowed types are ["feat", "fix", "docs", "style", "refactor", "test", "chore", "ci"] #错误示例2 feats: add login API #提示 error: unknown commit type `feats` help: did you mean `feat`? (similarity 0.80) note: allowed types: ["feat", "fix", "docs", "style", "refactor", "test", "chore", "ci"] 2.2 scope 校验 [header.scope] required = false allowed_scopes = ["core", "cli", "ui", "docs", "test"] required = true → 必须提供 scope required = false → 可选 若提供 scope,必须在 allowed_scopes 中 ⚠ allowed_scopes 不允许为空数组,若不需要校验,请注释掉整个字段。 2.3 subject 校验 [header.subject] spaces_after_colon = 1 forbid_trailing_period = true min_length = 2 max_length = 72 限制冒号后空格数量(默认为推荐的1个,建议不要修改) 禁止句号结尾(包含英文句号和中文句号) 限制 subject 长度 3. Body 校验 [body] required = false min_blank_lines_before_body = 1 forbid_trailing_whitespace = true min_line_length = 2 max_line_length = 72 默认可选 body和header之间的空行数量(不建议修改) 禁止行尾出现多余空格 限制 body每一行的长度 4. Footer 校验 [footer] start_key_words = ["BREAKING CHANGE", "Closes", "Fixes", "Signed-off-by"] footer部分的起始关键字 支持关键字拼写检查: [footer.start_key_words_spellcheck] enable = true threshold = 0.7 提交示例: feat: test footer Close: #123 错误提示: error: footer keyword appears misspelled: "Close" → "Closes" similarity = 0.83 (threshold = 0.70) ⭐ gitru 的两大特色能力 1. 跳过校验(Skip Validation) 虽然提交信息规范非常重要,但在实际开发中,总会遇到一些必须绕过校验的场景,这些提交往往不需要遵循团队的 commit 规范,甚至无法遵循。 因此,gitru 必须提供一种 安全、明确、可控 的方式来跳过校验。 在 Git 生态中,常见的跳过校验方式有三种: ① 命令行参数:git commit --no-verify Git 原生支持: git commit --no-verify 它会跳过所有 Hook,包括: commit-msg pre-commit prepare-commit-msg post-commit ② IDE 设置跳过 Hook 例如: JetBrains 系列(IDEA / PyCharm / RustRover) VSCode 不同IDE的设置不一致,有的需要设置中默认开启才会有对应操作,比如VSCode;有的选择跳过后如果忘记手动选回来,后续校验也会继续跳过。 ③ gitru 的方式:提交信息首行关键字 gitru 允许通过提交信息第一行完全匹配关键字来跳过校验: 注意:关键字可在配置文件中配置,但是严格区分大小写(当然,如果只是大小写不一致会有报错信息准确提示) 示例: SKIP fix: hotfix production issue 或: --no-verify feat: auto commit from script 默认配置下,以上提交都会直接跳过所有校验,并且在最终生成的校验信息中去除首行关键字。 2. 拼写检测(Spell Check) 由于规范约定缘故,body可选,中间可有空行,footer也是可选的,所以很难区分二者。gitru采用了footer配置关键字来区分。 这样一来footer校验严重依赖用户输入的单词,而人是最靠不住的,所以尽可能做点保障,校验用户是否拼写错误。 检测 footer 关键字是否拼写错误 避免 Clsoe、Fixex 这种低级错误导致自动化流程失效 使用相似度算法(默认阈值 0.7) 当检测到疑似拼写错误时,会阻止提交并给出友好提示 如果用户确认自己没错,就可以使用上一步提供的方法跳过校验强制提交。 footer提取关键字依赖:分割。 由于footer部分自由度太高,目前没想到完美的校验方法,好在我们大部分时间用到的是header和body校验。 🎉 总结 gitru 的目标不是取代现有工具,而是提供一个: 更轻量 更简单 更易安装 更适合非 Node/Python 项目 的 commit-msg 校验方案。 如果你在使用过程中有任何建议或问题,欢迎在 GitHub 提 issue,一起让这个小工具变得更好。