大家好,我是Zack。
前天下午我让 agent 改一个构建脚本,改完一跑就报错。
我把报错整段丢回去,说”修一下”。它改一版,我跑一次,还报错,再改。
改了三轮,还是同一个错。
最后发现这个错跟我改的代码一点关系都没有 —— 环境里少装了个包。
一下午,就这么没了。
我原来的做法
报错弹出来,我的动作是固定的:复制、粘贴、说”修一下”。
这个循环里藏着一个我从没检查过的前提:
这个错,真的是我这几行代码引起的吗?
我没验证过。我默认它是。
默认错了之后,后面每一轮都不是在修 bug,是在错误方向上加速。
三轮之后我才反应过来,方向从一开始就偏了。
现在多做一个动作
就一个:把改动收起来,重跑一次。
git stash -u # -u 是连没跟踪的新文件一起收
<你的运行命令>
git stash pop # 跑完记得 pop 回来
判据特别简单:
- 还报同一个错 → 跟你刚写的代码无关,是环境的事
- 不报了 → 就是你这几行,可以放心让它改
顺手提醒一句:跑之前先 git stash list 看一眼,确认stash 栈里没别人的东西。
这动作有多便宜
我在自己的博客仓库实测,402 个跟踪文件:
$ git ls-files | wc -l
402
$ time (git stash -q -u && git stash pop -q)
0.048 秒
在 /tmp 的小 demo 仓库里,加上中间那次重跑,整轮 0.103 秒。
不到 0.1 秒的动作,替我省掉一下午。
以前我觉得这种验证是”讲究人的做法”,要额外花时间。
实测完才发现,贵的从来不是验证,是验证之前那三轮瞎改。
第二步:看报错栈最后几行
我在 /tmp 故意引了个环境错误(代码里 require 了一个没装的包),真实输出长这样:
Error: Cannot find module 'lodash'
code: 'MODULE_NOT_FOUND',
requireStack: [ '/private/tmp/demo-stash/build.js' ]
重点看 requireStack 那一行 —— 它告诉你从哪个文件开始找的。
再配合一个粗判据:
- 栈里如果全是
node:internal/...、node_modules/...这种路径,最后才碰到你的文件 → 加载阶段就断了,多半是环境 - 栈顶直接是你刚改的那个文件、你刚写的那一行 → 那就是你的代码
这个判断不用很准,它是用来决定”下一步往哪查”的,不是用来结案的。
第三步:它说找不到文件,先让它打一行 pwd
agent 说”文件找不到”,十次有八次是它站的地方和你以为的不一样。
子 agent、脚本、定时任务,各有各的当前目录。
我自己踩过:同一个 build.js,站在仓库根目录跑好好的,cd 进一个子目录再跑,直接报 Cannot find module。
所以现在两件事我做死了:
- 下指令一律给绝对路径,不让它猜
- 让它在动手前先跑一句
pwd,把工作目录打出来给我看
第四步:给重试定个上限
不写上限,它会在同一个报错上一路转下去,转到你手动停。
现在我在任务里直接写死一句:
同一个错误最多重试 3 次,到了就停下来,把报错原文和已经试过的办法列出来给我。
上限不是限制它的能力,是给它一条能退出的路。
这条要跟第一步连着用:它停下来的那一刻,正好是你跑 git stash 的时机。
不是 node 也一样
这套判据跟语言没关系,git stash 是 git 的,不是 node 的。
Python 项目想快速确认”包到底装没装”,直接问解释器:
python -c "import 包名" # 报 ModuleNotFoundError 就是没装
pip check # 看已装的包之间有没有互相冲突
这两句跑完,环境那一半的可能性基本就排掉了。
验证完别留垃圾
git stash pop 之后顺手看一眼:
git status --porcelain # 只看未跟踪那部分
agent 跑完经常留一堆东西:tmp 目录、.bak、测试输出。
不管它,下次你 git add . 就全进仓库了。
要的留,不要的当场删。留着的下场是三个月后没人敢动。
前后对比
| 以前 | 现在 | |
|---|---|---|
| 归因方式 | 默认是自己的代码 | 先验证再动手 |
| 一次归因成本 | 三轮起步,一下午 | 0.05 秒 + 一次重跑 |
| 改错方向 | 全靠运气 | 基本不会 |
诚实说一句:那个 0.05 秒只是 git 命令本身,中间重跑一次要看你项目多大。
我这边的构建脚本重跑一次几百毫秒,加起来不满一分钟。
如果你的项目跑一次要十分钟,那这招依然划算 —— 十分钟能确认方向,比三轮瞎改便宜得多。
两条能迁移的原则
一、归因之前不动手。
花几十秒确认”这是谁的错”,看着慢,实际是把后面所有轮次的方向一次性定对。
二、判定不了的要求都是废话。
“修一下”判定不了,agent 只能猜。
“跑 git stash 确认是不是环境的锅”能打勾,它就能照做。
给 agent 下指令,先问自己一句:这条它做完了,我能不能一眼看出做没做到?
看不出来的,就还没写完。
最后
这套东西一点都不高级,就是几条现成的命令。
局限也说清楚:git stash 这招只在改动能干净收起来时好用。
如果一次改了几十个文件、还夹着没提交的配置,stash 本身就会变成新的麻烦 —— 这种时候我宁愿先 commit 一个临时节点,再从那个节点比对。
所以它不是万能钥匙,是个便宜的第一刀:先花 0.1 秒把”环境”这个最大的可能性排除掉,再谈别的。
你那边报错一般是怎么归因的?有没有比 git stash 更快的判据,欢迎留言告诉我。
公众号:Zack说AI