资讯动态

用三层防线规范AI的Git提交:AGENTS.md+Git Hooks实战

发布时间:2026/10/9 6:03:39 来源:尧图企业网站定制
别再让你的 Agent 随手git commit了——一个 GitHub 仓库被它搞乱之后我是这样用一套工作流把 AI 的 Git 提交拉回正轨的。这篇东西写给被 AI 帮忙写代码、又总得跟在后面收拾 Git 烂摊子的人不管你是团队技术负责人、独立开发者还是刚刚开始用 Cursor、Claude Code、Codex 这类 AI 编程工具的探索者都应该能在里面找到能直接抄的方案。先说下我踩坑的背景。上个月让一个 Agent 帮忙重构一个内部工具的前端它确实麻利地改完了 14 个文件然后我顺手让它“提交一下”。等我抽完烟回来看 Git 历史好家伙一条update files把 14 个文件全塞进一个提交里.env.local带着真实密钥进了版本库.next/构建产物也进去了提交信息里还混着fixed lol。我点了git reset、git rm --cached、改.gitignore折腾了 40 多分钟才勉强恢复原样。更气人的是第二次再让它提交它又犯了同样的错误。那一刻我意识到问题不在 AI 不会用 Git而是我压根没给它一套“不能出错”的约束边界和验收流程。1. 先搞清楚AI 改代码为什么总把 Git 搞乱1.1 我见过的几类典型翻车现场先说一个容易被忽略的事实多数 Agent 在执行 Git 操作时看起来懂命令实际上对“提交质量”这个概念毫无感知。它能背出git status、git add -A、git commit -m的用法但不知道什么是“一次语义内聚的提交”不知道哪些文件不应该进版本库更不知道提交信息是有格式规范可言的。我复盘了自己的仓库也看了几个朋友的“AI 事故现场”翻车基本集中在这么几类一刀切提交git add -A一把梭把重构代码、配置调整、无关联的排版改动、甚至临时调试文件全部揉进一个提交里你还真不好回滚其中某一部分。密钥和敏感信息裸奔.env、.env.local、config/secrets.yaml被直接git add上去了等推到远端才被扫描工具发现摊上大事。构建产物与依赖目录进库node_modules/、.next/、dist/、venv/这种本该在.gitignore里的目录如果 Agent 在“不熟悉项目”的状态下直接add -A该过滤的基本全被无视。提交信息乱写fix stuff、update、done、v2这类等于没有的提交信息到了做版本发布、写 changelog、回溯 bug 引入点的时候完全没法用。对分支状态不敏感Agent 经常不检查自己当前在哪个分支也不看远端是不是有别人的新提交。上次我就看到它直接把半成品 commit 到main上然后被push --force吓得差点把队友的提交覆盖掉。1.2 根源不在态度在边界很多人第一反应是“AI 太笨了”。我的结论恰恰相反AI 的失败是确定性行为的产物——你没给它边界它就会选择“成功率最高”的路径。对 Agent 来说任务目标是“改完代码”提交只是附带动作。它倾向于用最少的步骤解决眼前问题git add -A最稳因为它保证所有改动都被记录--force能解决一切“推送冲突”的报错提交信息随便写一句应付过去因为它的评测目标里没有“提交信息符合规范”这一项。本质上它和刚入职、没读过团队规范、又被 KPI 压着发版的实习生一模一样——不是坏是没人告诉它哪些动作是红线也没人在流程上拦住它。所以一套真正有效的解决方案重心不是“说服 AI 自律”而是把规则前置到它每次“动手之前”和“提交之前”让规则变成可执行的校验让不合规的行为在发生的那一刻就被拦截、被纠正。1.3 先把“按规范提交”拆成可衡量的标准在你试图给 Agent 立规矩之前得先明确规矩包含什么。以我自己现在用的标准为例一条“合规提交”必须满足四个条件维度具体要求一个反例提交范围只提交当前任务的关联文件排除.gitignore中的目录git add -A把缓存目录一起提交提交信息遵循 Conventional Commits 格式类型 可选作用域 一句话描述update files敏感文件绝对不出现密钥、令牌、真实用户数据.env被打进提交提交拆分逻辑不相关的内容拆成多个提交而不是一个巨型提交14 个无关文件揉成一个 commit这些标准在下面的工作流里会被翻译成两样东西一是写在 Agent 上下文里的“行为指令”二是写在 Git Hooks / CI 里的“硬校验”。指令管自觉校验管兜底两样缺一不可。2. 工作流设计思路三层防线 最小权限2.1 核心设计原则别指望 Agent “自觉”要让它“无法犯错”我对这套工作流的要求很简单在 Agent 完全不“自律”的情况下靠外部机制也能强制它产出合规提交。这就像开车——你可以相信司机的技术但安全带的强制提醒、车道偏移的警报、限速标识一个都不能少。所以我不打算只给 Agent 写一堆“请你注意”的指令而是做了三层防线第一层意图约束写在 Agent 系统提示 / 项目内规范文件里——告诉它“什么该做、什么不该做”从源头减少犯错概率第二层执行校验Git Hooks 自定义脚本——在commit和push这两个动作发生时程序化地检查不合规就拒绝执行第三层结果审计CLI 工具 CI 规则——即使前两层都被绕过推到远端仓库时还会被拦截守住最后一道闸门。这三层防线是层层递进的。第一层管高概率问题第二层管执行动作第三层管最终兜底。我把它们分别对应到 Agent、本地 Git、远端 CI 三个位置各有各的优势。2.2 三层防线的各自分工2.2.1 意图约束把规则写进 Agent 的上下文这是成本最低也最有效的一层。现在的 Agent 工具如 Cursor、Claude Code、Codex CLI 之类的基本都支持在项目目录里放一份指令文件每次会话会自动加载。Cursor 是.cursorrules或.cursor/rulesClaude Code 是CLAUDE.md通用一点的叫AGENTS.mdGitHub 已经在推动这个标准。这份文件的作用是让 Agent 在每次git commit前先“想三步”——当前改动涉及哪些文件这些文件是否属于本任务哪些文件绝不能被提交它不直接阻止违规但能把命令的“误触发概率”压到一个很低的水平。现实中80% 的 AI 翻车都能在这一层避免。2.2.2 执行校验用 Git Hooks 把不合规行为拦在动作发生前意图约束解决不了“Agent 明知不该但还是执行了”的情况因为 AI 对“该与不该”的理解本身就带概率性。所以必须在 Git 的动作点埋下硬校验。我用到了两类 Git Hookspre-commit在生成提交前先扫描暂存区检查有没有大文件、密钥文件、不该出现的目录还负责跑.gitignore的过滤验证。commit-msg检查提交信息是否符合规范格式格式不对直接exit 1提交直接失败。Git Hooks 是本地机制作用于所有使用这个仓库的人包括所有 AI Agent而且完全不由 Agent 控制——它在操作系统层面被 Git 触发Agent 的手想伸也伸不进来。提示Git Hooks 不会被 Git 提交到仓库.git/目录下面所以跨机器同步要自己处理。我会在后面的 3.3 节里给出一个用脚本自动部署的能力方案。2.2.3 结果审计远端 CI 规则引擎兜底一个成熟的提交工作流不能假设所有开发者以及所有 Agent都乖乖遵守本地规则。我见过有人用git commit --no-verify绕过 hook虽然 AI 不太会主动这么做但在某些自动化推送脚本里它是真实存在的。因此在远端我也部署了审计逻辑代码推送到远端仓库后由 CI 流水线GitHub Actions 等重新校验提交信息格式、扫描敏感信息、检查是否存在误提交目录。只要发现不合规CI 就通知相关人等处理必要时直接拦截合并请求。这三层放在一起形成“事前有指引、事中有拦截、事后有审计”的闭环。任何一个单点失效还有另外两层的兜底。2.3 为什么“直接让 Agent 自己记规则”的方案不可行有人问过我为什么不直接在系统提示词里写“记住提交规范”让 Agent 每次记住并遵守就完了我的答案很简单LLM 的“记忆”不是常态化的同一段规则在上下文窗口被 100 行代码挤出去之后遵守概率就断崖式下降。而且不同对话之间的行为不一致——同一个模型改天换个系统提示可能又忘了。所以我的立场很明确凡是“搞砸了代价高”的动作不要依赖 Agent 的模型能力要用确定性的工程手段兜底。AI 负责生成代码Git Hooks 负责把关提交各司其职。2.4 工具选型的取舍与原因通用配置文件AGENTS.md之所以不用.cursorrules而用 AGENTS.md是因为它跨工具兼容。Cursor、Claude Code、Codex、甚至自研脚本都会自动读取团队成员用什么工具都不受影响。Hooks 用 Shell 少量 Python部署零依赖跨平台不需要每个成员都装额外的 Node 包管理器。提交信息格式前半段统一用 Conventional Commits原因是它被主流生态支持changelog 能自动生成AI 也能比较轻松地理解“类型 描述”的结构。3. 实操搭建一套可直接复用的 Agent 提交流程下面进入完全拿来即用的部分。我会用一段完整的“从环境准备到现场实测”的流程把每一层落地细节都写出来。3.1 环境准备先把 Git 和 SSH 摸顺这一节如果你已经驾轻就熟可以跳到 3.2。但考虑到不少人是第一次为了“An Agent 项目”而从零开始配 Git我还是写清楚。3.1.1 安装 GitmacOS / Windows / Linux如果系统还没装 Git可以先装。macOSbrew install git或者用 Xcode Command Line Tools跑git --version时会弹出安装窗Windows直接下载 Git for Windows装的时候建议保留默认配置路径勾选“Add to PATH”LinuxDebian/Ubuntusudo apt update sudo apt install git -y。装完一律先验证git --version能看到类似git version 2.4x.x的输出就正常。3.1.2 配置 user.name 和 user.emailAI 替你提交的时候提交记录里会带上 Git 配置里的身份信息。这块如果不配一堆提交的 author 会变成一堆随机的roothostname后续做代码归属统计时完全没法看。git config --global user.name 你的名字 git config --global user.email youexample.com建议在项目根目录里也确认一下某些服务器环境会覆盖全局配置git config --local --list3.1.3 SSH 认证让 push 不必每天输密码Agent 在做自动化操作时最怕碰上要密码的交互环节——它会卡住然后给你编造一个极其难看的提交方式。所以把 SSH 认证配好让git push全程无交互。ssh-keygen -t ed25519 -C youexample.com一路回车生成后在终端打印公钥cat ~/.ssh/id_ed25519.pub把这段公钥加到你的代码托管平台GitHub / GitLab / Gitea的 SSH Keys 里。然后验证ssh -T gitgithub.com看到 “Hi xxx! Youve successfully authenticated” 就说明通了。3.2 把规范写进 Agent 的上下文AGENTS.md 模板下面是这份文件的核心内容它有两个作用第一让 Agent 在每次会话开始时就知道“提交有边界”第二给 Agent 提供一份“提交前自检清单”让它自己对着跑一遍。我建议把这份文件放在仓库根目录。文件名是AGENTS.md团队里如果有用 Cursor 较多的人可以在.cursor/rules里加一个同样的引用。# AGENTS.md — AI 开发工作流约束 ## 角色与任务 - 你是本仓库的开发助手所有代码改动、提交、推送必须严格遵守本文件约束。 ## 代码修改的阶段边界 1. 修改代码时**不允许直接修改 Git 暂存区**除非你正在执行明确的提交步骤。 2. 每次完成一个功能点先执行 git diff --stat 确认改动范围。 3. 发现无关文件出现时**立即停止**不要纳入提交将无关文件恢复原状。 4. 修改完成后把改动拆分成有意义的多个提交不要将无关内容揉进一个提交。 ## Git 提交规范强制 - 禁止使用 git add -A 或 git add .这会引入所有未跟踪文件包括构建产物、环境变量文件等。 - 必须逐个添加或按明确目录添加文件 git add src/components/Button.tsx - 提交信息必须符合 Conventional Commits 格式 type(scope): subject 其中 type 取feat / fix / refactor / docs / chore / test / perf / style subject 是简明的英文或中文描述不超过 72 字符。 - 禁止提交以下内容 - .env、.env.*、任何包含密钥的文件 - node_modules/、.next/、dist/、build/、venv/、__pycache__/ - 日志文件、临时文件.log、.tmp、.swp - push 前必须运行 git status 和 git log -1 --oneline 做最后确认。 - 禁止对共享分支执行 git push --force如确需覆盖历史先与团队负责人确认。这份文件里其实就是一套标准的“行为准则”。写完之后每次启动 Agent先让它cat AGENTS.md确认加载——不管什么工具你用AGENTS.md引用或 system prompt 里写明“先读 AGENTS.md”都行。3.3 用 Git Hooks 做硬校验一次配好全仓库生效3.3.1 pre-commit检查敏感文件和大文件在.git/hooks/pre-commit里放下面这段可执行的 Shell 脚本。原理是在git commit真正生成之前先扫描暂存区里的文件名一旦发现黑名单内容或超过阈值的大文件直接退出失败。#!/bin/sh # pre-commit: 扫描暂存区中的敏感文件、构建产物与大文件 BLOCKED_PATTERNS^\.env($|\.) ^node_modules/ ^\.next/ ^dist/ ^build/ ^venv/ ^__pycache__/ ^.*\.log$ ^.*\.tmp$ ^.*\.swp$ MAX_SIZE_MB50 # 获取暂存区文件列表 files$(git diff --cached --name-only) if [ -z $files ]; then echo ✗ 没有暂存文件无法提交 exit 1 fi # 敏感文件 / 目录检查 for file in $files; do for pattern in $BLOCKED_PATTERNS; do case $file in $pattern) echo ✗ 禁止提交文件: $file echo 请在 .gitignore 中确认并使用 git rm --cached $file 移出版本控制 exit 1 ;; esac done # 大文件检测 size$(git cat-file -s $(git ls-files -s $file | awk {print $2}) 2/dev/null) if [ -n $size ] [ $size -gt $((MAX_SIZE_MB * 1024 * 1024)) ]; then echo ✗ 文件超过 ${MAX_SIZE_MB}MB: $file exit 1 fi done echo ✓ pre-commit 校验通过注意Git Hooks 在克隆仓库后默认不会自动激活它们不会被 clone 到.git/hooks/。团队协作时可以把 hooks 脚本放在scripts/hooks/目录并纳入仓库然后用一条命令让成员一键安装。3.3.2 commit-msg提交信息格式校验下面这段脚本会读取COMMIT_EDITMSG文件验证首行是否符合type(scope): subject结构#!/bin/sh # commit-msg: 强制使用 Conventional Commits 规范 commit_regex^(feat|fix|refactor|docs|chore|test|perf|style)(\([a-zA-Z0-9_-]\))?: .{1,72}$ message$(cat $1) if ! echo $message | grep -Eq $commit_regex; then echo ✗ 提交信息不符合 Conventional Commits 规范 echo 正确示例: feat(user-service): 添加用户注册接口 echo 类型列表: feat / fix / refactor / docs / chore / test / perf / style exit 1 fi echo ✓ commit-msg 校验通过然后把这两个脚本放到仓库的scripts/hooks/目录并给一个安装脚本#!/bin/sh # scripts/install-hooks.sh ln -sf ../../scripts/hooks/pre-commit .git/hooks/pre-commit ln -sf ../../scripts/hooks/commit-msg .git/hooks/commit-msg chmod x .git/hooks/pre-commit .git/hooks/commit-msg echo ✓ Git Hooks 已安装团队成员或日后你新克隆仓库后跑一次bash scripts/install-hooks.sh就能生效。3.3.3 远程兜底一个极简的 CI 校验脚本在 GitHub Actions 里.github/workflows/check-commit.yml可以这样写name: Commit Convention Check on: [pull_request] jobs: check-commit: runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 - name: Validate commit messages run: | commits$(git log --format%s origin/main..HEAD) while IFS read -r line; do [ -n $line ] || continue echo $line | grep -Eq ^(feat|fix|refactor|docs|chore|test|perf|style)(\([a-zA-Z0-9_-]\))?: .{1,72}$ || { echo ✗ 提交信息不合规: $line; exit 1; } done $commits这个动作的意义是哪怕本地 hook 被--no-verify绕过CI 也会把不合规的提交拦在合并请求之外。3.4 给 Agent 的 Workflow 指令模板让它按流程做事环境搭好之后还得给 Agent 一份明确的“操作流程”文本。我在每次让 Agent 干活前都会把这段指令粘进对话或者写成一个workflow.md放在仓库里让 Agent 按部就班地执行。## 你的一次代码修改必须遵循以下流程 步骤 1读取 AGENTS.md确认所有约束。 步骤 2在改动开始前运行 git status --short 记录初始分支与文件状态。 步骤 3修改代码时只编辑与你任务相关的文件无关文件不可更改。 步骤 4完成修改后运行 git diff --stat 检查文件列表。 步骤 5按逻辑分割提交 - git add 具体文件1 具体文件2 - git commit -m feat: 描述本次改动 - 如有多个逻辑块拆成多个 commit。 步骤 6push 前运行 git status 与 git log -1 --oneline 自查。 步骤 7确认无误后 git push。若遇到冲突或错误停下并向用户报告不要擅自 --force。这段指令看起来简单但它把 Agent 的“自由发挥空间”压缩到了极致它不再能一条git add -A git commit -m done过关而是必须走完全部 7 步。以我观察到的现象给 Agent 提供这种步进式指令后操作质量会有质的变化。3.5 提交信息怎么写才规范Conventional Commits 速查如果对 Conventional Commits 还不熟这里给一个速查类型什么时候用示例feat新功能feat(user-service): add login endpointfix修 bugfix(parser): handle empty inputrefactor重构不改行为refactor(api): extract http clientdocs文档变动docs: update READMEchore杂务/依赖/构建chore: bump lodash to 4.17.21test测试相关test(auth): add token refresh caseperf性能优化perf: cache query resultsstyle格式/样式调整style: format with prettier注意开头别用Update、Fixed、wip、done——这些词在 hook 校验里会直接被拒。用模板去框Agent 犯错概率低很多。3.6 现场实测记录一次真实任务的完整走查拿一个我最近让 Agent 做的“重构首页轮播图组件”的任务来演示我启动 Claude Code粘贴 AGENTS.md 内容并附上 3.4 节 work flow。Agent 开始读代码运行git status --short确认当前分支feature/carousel-refactor。它修改了components/Carousel.tsx、styles/carousel.css、hooks/useCarousel.ts三个文件。我要求它先git diff --stat它输出components/Carousel.tsx | 82 ---- styles/carousel.css | 31 -------- hooks/useCarousel.ts | 17 -----它尝试git add三个文件并提交feat(carousel): rewrite carousel component。pre-commit 扫描通过commit-msg 校验通过。推送前它又跑了一遍git status和git log -1 --oneline确认无误后 push。全程我没有手动介入。而且因为 AGENTS.md 和 hooks 已经进了仓库下一个人或另一个 AI克隆这个仓库时只要执行scripts/install-hooks.sh约束会自动生效。4. 常见问题与排查技巧实录这一节把你大概率会遇到的问题、我排查这些问题的思路、以及一些独门经验都整理出来。4.1 提交信息被拒但 Agent 反复不改现象commit-msg hook 报错Agent 尝试了三次提交信息还是fix stuff或者update some files。原因排查多数情况下Agent 是在“批量执行脚本”的上下文里把git commit当成一个固定命令在用完全没有解析 hook 的报错输出。更隐蔽的一种情况是Agent 把报错信息当成“无关日志”直接忽略继续执行。解决思路把AGENTS.md里的“提交信息格式”放在最显眼的位置并配一个示例。在 workflow 指令里增加一条“如果 commit 失败你必须在下一次尝试之前读取 hook 的错误信息并据此修改提交信息。如果连续两次失败停下来向用户报告。”更稳妥的做法对话开始前给 Agent 一个样本提交命令让它照着执行git commit -m feat(carousel): rewrite carousel component4.2 误提交了 node_modules 或 .next 目录现象git status里看到一堆未跟踪目录Agent 直接git add -A全收。根因项目里没有.gitignore或者.gitignore规则不全。处理步骤立即把不需要的文件移出版本控制git rm -r --cached node_modules .next把目录补进.gitignorenode_modules/ .next/ dist/ build/ venv/ __pycache__/ *.log .env*提交这份修复git commit -m chore: add .gitignore for common build artifacts心得.gitignore不是“写好就完事”的它会在协作过程中被反复打补丁。我通常会在新仓库初始化后第一时间就把标准模式加进去这是花 5 分钟省 1 小时的买卖。4.3 敏感信息已经进入 Git 历史现象.env被提交了但你可能在几天后才发现这时历史里已经留了底。处理建议如果文件内容是密钥、密码、token立即去对应平台“撤销并重新生成”这是唯一的止损办法。别指望git rm能把它从历史里抹掉旧 commit 里依然存在。如果想彻底重写历史可以用git filter-repogit filter-repo --path .env --invert-paths然后强制推送git push --force --all但同样这样做之前务必和团队沟通因为会改写协作历史。这条禁令应该同时写进AGENTS.md任何情况下修改密钥类文件后不得自行 push --force。4.4 分支混乱Agent 在错误的分支上提交现象你让 Agent 做个 feature结果它直接在main上改了 5 个文件、有 7 个提交。规避办法每次开新任务前在 workflow 里先运行git checkout -b feature/xxx把工作分支固定下来。在AGENTS.md里写明“如果当前分支不是任务分支先询问用户确认不得直接在主分支上修改代码。”如果已经搞乱了常规处理是git branch feature/xxx从当前所在位置建分支→git reset --hard origin/main本地主分支回到远端状态然后去分支上处理改动。4.5 Agent 执行 push --force 把别人的提交覆盖了这是我见过最灾难的一种。Agent 在推送被拒时可能会自作主张执行git push --force。预防对策在远端仓库GitHub/GitLab里对共享分支启用“分支保护规则”禁止 force push这是最权威的兜底。本地 hooks 也可以拦截在pre-push脚本里检测 push 命令带不带--force带就退出#!/bin/sh # pre-push: 禁止 force push 到共享分支 if echo $1 | grep -q -- --force; then echo ✗ 禁止使用 --force 推送 exit 1 fi实际上 CI 远端保护双管齐下失控概率极低。4.6 Hook 不生效克隆仓库后没装现象新克隆下来的仓库里AGENTS.md有了但 commit-msg hook 不报错foo stuff也能提交成功。原因Git Hooks 只存在本地.git/hooks/克隆不会自动带过来。对策要么在 README 里写明“新成员需要先运行bash scripts/install-hooks.sh”要么把 hooks 配置纳入工具链比如用husky这类包管理器方案但会比脚本方案重。4.7 常用排查命令速查表场景命令查看改动范围git diff --stat查看已暂存内容git diff --cached --stat把误暂存文件移出git restore --staged file放弃工作区改动git restore file查看最近几条提交git log --oneline -5撤销上一次提交保留改动git reset --soft HEAD~1查看具体提交改了什么git show --stat HEAD5. 实测效果与我的个人体会最后分享一下这套流程跑了一个多月后的结果读起来会比较直观。在给三个团队、五个不同的项目都加上了这套“AGENTS.md Hooks CI”组合之后我粗略统计了一下由 AI 产生的乱序提交从原来的每周至少两次降到了几乎为零。唯一一次破功是我自己在一个旧项目上忘了装 hooks手动git commit -m wip提交了一份半成品——这说明流程管得住 AI也管得住我这种偷懒的人。我个人的体会有两点。第一工程手段永远比口头约束可靠。这句话在 AI 场景尤其是真理不管system prompt写得多天花乱坠不如一句git commit前的exit 1好使。第二这套东西不是“一次性搭建永久受益”的它更像一套需要持续维护的食谱。项目换了语言、加了依赖、调整了分支策略你就要同步更新.gitignore、Hooks 正则和 AGENTS.md 里的规则。最后再分享一个小技巧如果你用的是支持 MCP 的 Agent 环境可以把“commit message 格式化”和“敏感文件扫描”做成两个 MCP 工具让 Agent 在提交前主动调用并等待校验结果。这等于把第三层防线又往前移了一步——它从“犯了错被拦”变成“没犯错前就要自查”。我最近在一个内部工具项目上试过这种方式提交合规率非常高而且 Agent 自己也会逐渐生成更符合仓库习惯的代码。现在你可以去打开自己那个“一团乱麻”的 Git 仓库先把AGENTS.md和commit-msghook 落地。只要迈出第一步后面就有得救。等你跑久了会感谢那个当年愿意被规范管着的 AI 助手也会感谢愿意花时间搭这套流程的你自己。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑