周四下午4点半,同事在群里@我:
"你刚才合并的代码把我的数据同步接口搞挂了,线上已经开始报错。"
我立刻打开Git历史。合并记录显示:我的feature分支合并进了release,但提交列表里不只有我的改动,还混入了另外两个同事正在开发中、没测完的功能代码。
这些代码随着release分支自动部署,触发了线上数据异常。
紧急回滚、数据清理、开复盘会……那一刻我意识到一个问题:
AI改代码的速度越来越快,但我检查代码的速度没有跟上。
更可怕的是,我甚至没意识到应该检查什么。
AI改了什么,我真的知道吗?
事故发生前10分钟,我是这么操作的:
我让Claude Code帮我合并feature分支到release,处理一些冲突。
帮我合并XX分支,解决这些冲突AI很快搞定了,给我看了一下改动。我扫了一眼,没发现明显问题,觉得没什么大不了的,就推送了。
但我没有做这件事:
# 看看到底要合并哪些提交git log --oneline release..feature/recommend-api
如果我当时跑了这个命令,会看到提交列表里有其他人的commit。那一刻我就应该停下来。
后来复盘才发现,真正的问题不是Git乱合并,也不是AI神奇地改坏了分支,而是我没有让AI做"合并范围校验"。
分支里到底有哪些commit、哪些文件会进release,我没有先确认。
AI会处理操作,但不会替你判断边界。

第二次事故:AI的"好心"
两周后,类似的问题又发生了。这次是AI"顺手帮我清理了无用代码"。
我让AI写一个新接口,替换旧的数据查询逻辑。AI写完后,看到旧接口不再使用,就把UserMapper.xml文件删了。
编译通过,本地测试通过(我只测了新接口)。第二天上线后,同事发现他负责的数据同步功能失效了——他的接口也在用这个Mapper.xml,被我删了。
Maven编译不会检查Mapper.xml是否被其他地方引用,因为这是运行时加载的。AI不知道这个文件被多个接口共享。

我发现真正危险的不是写错,而是改动边界失控
两次事故后,我开始意识到问题不在于AI写的代码对不对,而在于:
AI不知道它可以改什么,不可以改什么。
更准确说:
AI不知道合并分支时应该只包含我的提交
AI不知道Mapper.xml可能被其他接口共享
AI不知道什么文件可以删,什么文件不能碰
AI不知道什么操作风险高,需要人工确认
我之前的用法是:丢给AI一个需求,让它去做。做完了我看一眼,没发现明显问题就提交。
这种用法的前提是:AI知道边界在哪里。
但它不知道。
我后来只加了三道闸
现在回头看,我需要的不是更强的AI,而是更清楚的边界。
我给AI编码加了三道闸:

第一道闸:明确哪些操作AI不能直接执行
我在项目根目录放了一个CLAUDE.md文件,写清楚AI不能做什么:
# 严禁AI执行的操作- git push到release/master- git merge到release/master- 删除文件(除非我明确要求)- 改动我没有要求的文件- "顺便优化"或"清理无用代码"
CLAUDE.md不是保险箱,它只是让AI每次进入项目时先看到规则。真正起作用的,还是我后面有没有按规则检查diff、提交范围和风险点。
现在任何Git操作,我都让AI给出命令建议,但不让它直接执行。AI可以帮我分析冲突、给方案,但最终操作必须我自己做。
更重要的是,合并前我一定会先跑这两个命令:
git log --oneline release..feature/recommend-apigitdiff--stat release...feature/recommend-api
这里的关键不是背命令,而是确认:即将进入release的提交,是否全部属于本次需求。
如果提交列表里有我不认识的commit,或者文件改动超出预期范围,就停下来排查,而不是直接推送。
第二道闸:diff必须看删除操作
第二次事故后,我改变了看diff的方式。
以前我主要看AI加了什么代码,现在我重点看AI删了什么:
gitdiff--stat# 先看文件列表,重点关注deleted filegitdiff# 再看具体改动
如果diff里有deleted file,我必须确认:
这个删除是我明确要求的吗?
这个文件是否被其他地方引用?
对于Mapper.xml这种共享文件,我不会只看文件名,而是会搜namespace、Mapper接口、SQL id,确认没有其他接口还在调用:
grep-r"namespace=\".*UserMapper" .grep-r"selectUserById" .grep-r"UserMapper" src/main/java
现在我让AI改代码时,会明确告诉它:
写一个新接口实现XX功能注意:- 只写新接口,不要动旧接口- 不要删除任何文件- 不要"顺便优化"其他代码
把边界说清楚,比事后检查省力得多。
第三道闸:改动前先让AI列出影响范围
对于复杂改动,我现在不会直接让AI执行,而是先让它给个Plan:
Research一下XX功能涉及哪些模块Plan一下如何实现,列出:1. 需要改哪些文件2. 可能的风险(缓存/配置/定时任务)3. 测试点Plan确认后再Execute
看到Plan后,我会追问AI容易漏的点:
Plan里没看到缓存处理,这个改动会影响缓存吗?Plan里没提定时任务,定时任务需要改吗?配置文件需要同步吗?
这些问题不能指望AI每次都主动想到。你不把它写进Plan要求里,它就可能漏。
我按风险给AI的操作分了三档

现在我会根据风险决定AI能做什么:
禁止AI直接执行(必须人工操作):
release/master分支操作
删除文件
数据库迁移脚本
AI可以做,但必须先Plan并人工确认:
跨3个以上文件的改动
涉及缓存、定时任务
涉及公共Mapper.xml、工具类
AI可以直接做,但我必须看diff:
注释、日志
单文件小修改
这个分级不是为了限制AI,而是为了让我清楚什么时候应该停下来检查。
这套边界在工程里叫什么?
2026年前后,Mitchell Hashimoto、Martin Fowler等人都在讨论类似的Harness Engineering:不是只换更强的模型,而是给Agent设计更可靠的工作环境。
这个概念我不是想展开讲。对我来说,Harness Engineering最有用的一点就是:不要只盯模型强不强,而要设计一套让AI不容易越界的工作环境。

我的理解是:不求模型更"聪明",而是通过工程手段防止同样错误再次发生。
每次AI出错,我都会问自己:
这个错误是什么
为什么会犯这个错
如何避免下次再犯
然后把规则补充到CLAUDE.md里,或者改进我的Prompt。
比如误删Mapper.xml后,我在CLAUDE.md里加了一条:
# 特别注意- Mapper.xml可能被多个接口共享,删除前必须全局搜索引用
Git事故后,我把"禁止AI操作release分支"写进了规则。
不只是改这一次,而是改规则,让AI以后不再犯。
你现在可以做的三件事
如果你也在用AI写代码,这三件事可以立刻做:
1. 创建一个CLAUDE.md,写下禁止事项
至少包含:
AI不能直接操作的分支(release/master)
AI不能做的操作(删除文件、顺便优化)
项目的特殊约束(共享Mapper、缓存逻辑)
2. 下次合并前先跑git log
git log --oneline release..feature/xxx看看到底要合并哪些提交,确认都在预期范围内。
3. 记录下一次AI出错
问三个问题:
错误是什么
为什么会犯
如何避免下次再犯
把答案写进你的CLAUDE.md。
写在最后
AI改代码的速度确实快,但如果不给它画边界,出问题也很快。
这篇文章记录的是我踩过的两个坑,以及我后来补上的三道闸。我不敢说这套方法完美,但至少让我知道什么时候应该停下来检查。
AI不是银弹。关键是知道它能做什么,不能做什么。
后面我会把这套检查清单整理成一份更完整的版本,尤其是Git、Mapper、缓存、配置、定时任务这几类高风险点。不是为了做资料,而是为了以后少踩同一种坑。
关于作者
我是Leon,Java后端开发,专注推荐系统和搜索业务。这3个月最大的收获不是AI帮我写了多少代码,而是我开始学会给AI改代码画边界。
如果你也用AI改过真实项目,我更想看你踩过的坑。尤其是:
AI有没有动过你没让它动的文件?
你是怎么防止AI"顺便优化"的?
欢迎在评论区聊聊。
夜雨聆风