Codex修改代码后找不到改了哪里?Diff、Git状态与文件变更检查教程
用 Codex 修 Bug 时,有一种情况非常常见:
它明明一直在改,但问题就是解决不了。
你可能会看到这样的循环:
- 第一次修改后,原来的报错没了;
- 运行项目,又出现一个新的错误;
- Codex继续修改;
- 新错误解决了,旧问题又回来;
- 连续折腾几轮,改动文件越来越多;
- 最后项目比一开始还难排查。
这时候很多人的第一反应是:
“是不是模型能力不够?”
但实际开发里,更常见的原因并不是模型完全不会修,而是:
上下文不完整、真实报错没给够、任务范围太大,或者验证流程本身有问题。
如果 Codex 已经连续修改几轮仍然失败,建议先停下来,不要继续让它无方向地改。
一、先判断它是不是在“猜Bug”
最典型的问题就是:
你只告诉 Codex:
登录功能坏了,帮我修一下。
或者:
项目报错了,继续修。
但没有提供:
- 完整错误信息;
- 复现步骤;
- 预期结果;
- 当前环境;
- 最近修改了什么。
这种情况下 Codex 只能根据代码推测。
第一次猜错以后,后面的修改很容易继续建立在错误假设上。
结果就是:
越修越偏。
更好的方式是先停止修改,让它只做分析。
例如:
暂时不要修改任何代码。
请先分析当前Bug:
1. 复现路径是什么;
2. 实际报错是什么;
3. 最可能的3个原因是什么;
4. 分别需要检查哪些文件;
5. 先告诉我排查顺序。
先让它建立一个故障模型,再开始动代码。
二、一定要给“完整报错”,不要只截最后一行
很多报错真正有价值的信息,并不在最后一句。
例如你只给:
TypeError: undefined
信息量其实非常少。
完整报错可能还包含:
at getUser()
at authMiddleware()
at loginHandler()
at router()
这条调用链能够直接告诉 Codex:
错误是从哪里一路传过来的。
如果只给最后一句,它可能去改最终报错的位置。
但真正的根因可能在更上游。
所以遇到 Bug 时,最好把这些一起提供:
- 完整错误堆栈;
- 触发错误的命令;
- 对应输入;
- 复现步骤;
- 错误发生前后的关键日志。
信息越完整,Codex越不需要猜。
三、不要一句“还是不行”,要告诉它哪里不行
很多人使用 AI 调试时喜欢说:
还是不行。
这句话对人来说很好理解,但对调试几乎没有帮助。
因为“还是不行”可能代表:
- 原错误完全没变;
- 原错误消失,但出现新错误;
- 项目能启动,但业务功能错误;
- 测试失败;
- 页面能打开,但数据异常。
最好改成:
上一次修改后:
原来的数据库连接错误已经消失,
现在项目可以启动,
但提交登录表单时返回500。
新的完整报错如下:
……
这样 Codex才能知道:
上一步到底有没有起作用。
否则它可能把已经修好的部分又重新改坏。
四、连续失败两三轮后,要重新建立上下文
如果已经修改很多轮,当前对话里往往会同时存在:
第一版方案;
第二版方案;
第三版报错;
已经废弃的假设;
后来新增的文件。
这时候再继续一句:
接着修。
模型需要在大量旧信息中判断哪些还有效。
很容易混乱。
更稳定的做法是重新汇总当前状态:
重新基于当前代码排查,不要沿用之前的结论。
当前状态:
1. 项目可以正常启动;
2. 登录接口返回500;
3. 数据库连接正常;
4. 问题只发生在Google登录;
5. 当前完整报错如下……
请重新定位根因。
如果对话已经非常长,甚至可以直接开一个新任务。
带上:
当前代码状态 + 最新报错 + 复现步骤。
很多时候比继续在旧上下文里打补丁更快。
五、任务范围太大,也容易陷入循环
例如你告诉 Codex:
用户系统有问题,全部帮我修好。
这可能涉及:
- 登录;
- 注册;
- Token;
- 数据库;
- 权限;
- 前端状态;
- 缓存;
- 测试。
如果同时改太多东西,就会产生一个问题:
你根本不知道是哪一个修改带来了新的错误。
更好的方式是拆任务。
例如:
第一步:
只定位为什么登录接口返回500,不修改前端。
第二步:
修复后只运行登录相关测试。
第三步:
确认后再检查Token刷新。
第四步:
最后再跑完整测试。
每一步只解决一个明确问题。
这就是调试中非常重要的原则:
缩小故障范围。
六、不要让Codex一次改十几个文件
如果一个 Bug 理论上只是一个小问题,但 Codex 一次改了:
15 files changed
就应该警惕了。
并不是说改得多一定错。
但修改范围越大,越难判断新错误从哪里产生。
可以直接限制:
先不要重构。
只修改解决当前Bug必需的文件,
如果认为需要改超过3个文件,
先解释原因,不要直接执行。
这样能减少“为了修一个Bug,顺手重构半个项目”的情况。
实际调试时,小 Diff 通常比大规模修改更容易验证。
七、先复现,再修改
这是一个非常重要但经常被忽略的步骤。
如果 Codex根本没有稳定复现问题,就直接开始改代码,那么很难判断:
修改以后到底有没有真正解决问题。
比较理想的流程是:
复现Bug
↓
记录当前报错
↓
修改
↓
使用同样步骤再次复现
↓
确认Bug是否消失
例如原问题是:
用户连续登录两次后页面白屏。
那么修复以后,也应该按照同样流程:
连续登录两次。
而不是只看:
npm test通过了,所以应该没问题。
测试通过只是一个信号。
真正的原始问题也要重新验证。
八、发现新错误时,先判断是不是“次生错误”
Codex修复一个Bug后出现新错误,并不一定代表修改完全失败。
例如原来的问题是:
数据库连接失败
修复以后变成:
user not found
这可能说明:
程序已经成功走过数据库连接阶段。
新的错误反而证明前一步修复有效。
所以不要看到新报错就马上说:
你又修错了。
应该先判断:
错误发生的位置是不是往后推进了。
如果程序执行路径已经更进一步,那么这是新的问题,而不是原问题没修好。
这也是调试时很重要的思路:
观察故障位置有没有变化。
九、不要让它为了通过测试不断修改测试
如果 Codex 连续修Bug失败,有时候会开始修改测试。
比如原本测试要求:
错误密码返回401
但当前代码返回200。
一种危险的做法就是直接把测试预期改成200。
这样测试当然绿了。
但Bug并没有修好。
所以调试时可以提前加一个限制:
不要修改现有测试的预期结果。
除非你能明确证明测试与当前需求不一致,
否则优先修改实现代码。
尤其是已经存在很久的回归测试,不能为了让当前代码通过而随便改。
十、让Codex每轮只验证一个假设
真正有效的调试,不应该是:
可能这里有问题,我把这几个地方全改了。
而应该是:
提出假设 → 验证假设。
例如:
假设1:
Token没有正确读取。
那就先检查Token值和调用链。
如果正常,就排除。
假设2:
数据库查询返回空。
继续验证。
假设3:
权限中间件提前拦截。
继续验证。
一次只验证一个最可能原因。
这样即使最后没修好,你至少知道:
哪些原因已经排除了。
而不是改了20处以后,完全不知道哪个改动真正有效。
十一、一个更稳定的Codex Bug排查模板
以后遇到反复修不好的Bug,可以直接把任务改成下面这种结构:
当前Bug:
用户登录后接口返回500。
复现步骤:
1. 启动项目;
2. 打开登录页;
3. 输入正确账号;
4. 点击登录。
预期结果:
返回200并进入首页。
实际结果:
返回500。
完整报错:
……
当前已确认:
1. 数据库可以连接;
2. 用户记录存在;
3. 前端请求参数正确。
要求:
1. 先分析,不要修改;
2. 给出最可能的3个根因;
3. 按优先级逐个验证;
4. 一次只处理一个根因;
5. 不重构无关代码;
6. 修复后执行原始复现步骤和相关测试。
这种提示方式,比一句:
帮我修这个Bug。
稳定得多。
十二、什么时候应该停止继续让Codex修?
如果出现下面几种情况,就应该先停:
同一个问题连续修改3轮以上;
每轮修改文件越来越多;
原Bug还没定位,就不断出现新改动;
开始频繁修改依赖和配置;
为了通过测试开始改测试预期;
已经无法解释每个文件为什么修改。
这时候不要继续堆修改。
先:
git status
git diff
确认当前状态。
必要时回到一个已知可运行的版本,再重新开始排查。
最后
Codex反复修改一个Bug却始终失败,很多时候真正缺少的不是“再生成一次代码”。
而是:
更清楚的问题定义和验证流程。
遇到这种情况,可以记住一个顺序:
拿到真实报错 → 稳定复现 → 缩小范围 → 提出假设 → 一次验证一个原因 → 小范围修改 → 再复现。
AI调试最怕的不是第一次猜错。
真正危险的是:
第一次猜错以后,还沿着错误方向连续修改十几轮。
所以当Codex开始陷入循环时,最有效的操作往往不是告诉它:
“继续修。”
而是先让它停下来,重新回答一个问题:
“我们现在到底确定了什么?”
持续更新 Codex、大模型开发与 AI 编程实战内容,整理 ChatGPT Plus/Pro、AI会员订阅及常见使用问题。更多深度内容,欢迎搜索关注「仙逆GPT」。
更多推荐



所有评论(0)