Git Pre-commit Hook — 自动 Lint 与格式化暂存区文件
无需 Husky 的轻量级 Git 钩子方案:自动格式化 Markdown、代码 Lint 校验以及 Mermaid 图表语法检查。
在日常团队协作或文档维护中,确保每次提交前的代码规范和文档排版一致性至关重要。无需依赖庞大的第三方 npm 库,直接利用 Git 原生 Hooks 配合 core.hooksPath 即可搭建一套零依赖的高效提交流程。
flowchart TD
Start(["开发者执行 git commit -m '...'"]) --> Hook["触发 .githooks/pre-commit 脚本"]
Hook --> Step1{"1. 检查暂存区 Markdown 文件<br/>(.md, .mdx)"}
Step1 -->|存在文件| Formatter["执行 agent-md format<br/>自动 git add 变更"]
Step1 -->|无| Step2{"2. 检查暂存区代码文件<br/>(.ts, .tsx, .astro...)"}
Formatter --> Step2
Step2 -->|存在文件| Linter["执行 bun lint (ESLint)<br/>自动 git add 变更"]
Step2 -->|无| Step3{"3. 检查暂存区文档与图表"}
Linter --> Step3
Step3 -->|存在文件| MermaidLinter["执行 bun lint:mermaid (maid)"]
Step3 -->|无| Done(["提交成功 ✅"])
MermaidLinter -->|存在语法错误| Abort(["中断提交 ❌<br/>需修复错误后重试"])
MermaidLinter -->|校验通过| Done
为什么选择原生 Git Hook 而非 Husky?#
flowchart LR
subgraph HuskyApproach["Husky 方案"]
H1["需安装 npm 依赖包"]
H2["增加 node_modules 体积"]
H3["依赖 Node.js 外部运行封装"]
end
subgraph NativeApproach["Git 原生 Hook (core.hooksPath)"]
N1[".githooks/ 目录下单个 Shell 脚本"]
N2["零依赖 (Zero Dependencies)"]
N3["天然跟随 Git 仓库版本管理"]
end
| 评估维度 | Husky / 第三方工具 | Git 原生 Hook (core.hooksPath) |
|---|---|---|
| 依赖引入 | 需安装额外 npm 包 | 0 依赖 |
| 执行效率 | Node.js 封装启动有延迟 | Shell 脚本毫秒级启动 (<10ms) |
| 团队共享 | 支持 | 支持(直接跟随 Git 仓库提交) |
完整 Pre-commit 脚本实现#
在 .githooks/pre-commit 中添加以下代码:
#!/usr/bin/env bash
set -e
# 1. Format staged markdown files with agent-md if available
if command -v agent-md >/dev/null 2>&1; then
STAGED_MD_FILES=$(git diff --cached --name-only --diff-filter=d | grep -E '\.(md|mdx)$' || true)
if [ -n "$STAGED_MD_FILES" ]; then
echo "[git-hook] Running agent-md format on staged markdown files..."
for file in $STAGED_MD_FILES; do
if [ -f "$file" ]; then
agent-md "$file"
git add "$file"
fi
done
fi
fi
# 2. Lint changed code files with bun lint
STAGED_CODE_FILES=$(git diff --cached --name-only --diff-filter=d | grep -E '\.(js|jsx|ts|tsx|astro)$' || true)
if [ -n "$STAGED_CODE_FILES" ]; then
echo "[git-hook] Running bun lint on staged code files..."
bun lint
for file in $STAGED_CODE_FILES; do
if [ -f "$file" ]; then
git add "$file"
fi
done
fi
# 3. Lint mermaid diagrams with bun lint:mermaid
STAGED_DOC_FILES=$(git diff --cached --name-only --diff-filter=d | grep -E '\.(md|mdx|html|astro)$' || true)
if [ -n "$STAGED_DOC_FILES" ]; then
echo "[git-hook] Running bun lint:mermaid on diagrams..."
bun lint:mermaid
fibash核心逻辑解析#
1. 借助 git diff --cached 仅处理暂存区文件#
flowchart LR
GitIndex["Git 暂存区 (Staged Area)"] --> Filter["git diff --cached --name-only --diff-filter=d"]
Filter --> Regex["grep -E '\\.(后缀)$'"]
Regex --> Files["目标处理文件列表"]
--cached:仅检查已被git add的暂存区文件,避免全量扫描浪费性能。--diff-filter=d:排除已删除的文件,防止脚本尝试读取不存在的文件报错。set -e:遇到任何检查失败立即终止流程,阻止错误代码入库。
2. 自动重新暂存(Re-stage)#
当格式化工具(如 agent-md 或 eslint --fix)修复了文件内容后,脚本通过 git add "$file" 将最新修改直接打入本次提交中,无需开发者再次手动添加。
项目中配置自动启用#
在 package.json 中配置 prepare 脚本:
{
"scripts": {
"prepare": "git config core.hooksPath .githooks",
"lint": "eslint --fix 'src/**/*.{js,ts,jsx,tsx,astro}'",
"lint:mermaid": "maid docs/ src/"
}
}json添加执行权限并初始化:
chmod +x .githooks/pre-commit
bun run preparebash总结#
只需一个简洁的 Shell 脚本,即可实现:
- Markdown 文档自动格式化排版。
- TypeScript / Astro 源码 ESLint 自动修正。
- Mermaid 架构图语法准确性校验。