返回博客

「已修复」与「还是坏的」同时成立:先查代码有没有部署再说

开发那边 typecheck 通过、lint 干净、单测绿灯,一句"已完成,等待验收"。测试打开页面,原来的问题一字未改,原封不动地重现。双方都没有说谎——但他们根本不是在看同一份代码。

这个坑我亲历过:测试报"还是坏的"之后,我们派出两个资深 agent 重新诊断,花了半小时分析 SSoT 漂移、seed JSON 不一致、fail-insecure fallback……最后发现:开发的修复从没 commit 过,用户浏览器跑的是几个小时前的老构建。两分钟的 git status 本可以直接结案。

现象

  • 开发:「我在本地跑,确实没问题了。」
  • 测试:「我打开页面,和之前一模一样,没有任何变化。」
  • 双方都有截图,双方都很确定。

这种对话通常有两种反应:①默认开发没改对,重新分析根因;②默认测试操作有误,让他重现。两种都容易走弯路。

根因

"已修复"是一个三阶段信号,现实中经常被压缩成了一个:

| 阶段 | 含义 | |------|------| | (a) 代码已写完 | working tree 里改了,本地 dev server 能看到 | | (b) 已 commit / push | 进了远端仓库,CI 可以拿到 | | (c) 已部署 | 用户访问的环境跑的是新代码 |

开发说"修好了"通常指 (a)。测试验的是 (c)。两个人对同一句话的理解相差两跳,完全不重叠。

坑:「done」信号折叠了三个不同状态

"代码写完"≠"已提交"≠"已上线"。任何一步没做,测试就永远验不到那个修复——但开发本地的 hot-reload 让他完全感知不到这个断层。尤其在多人协作、CI/CD 异步部署的场景,这个断层出现的频率极高。

正解

在派出任何"再诊断"之前,先机械地走完这四步检查,耗时不超过两分钟:

Step 1:在每个涉及的 repo 跑 git status

git status --short

若修改的文件还列在输出里 → 代码在 working tree,从未进仓库。答案就是:commit → push → 重新部署。不需要重新诊断。

Step 2:对比线上构建版本与 HEAD

让测试告诉你页面右下角的构建戳(或 /version 接口返回的 SHA),然后:

git rev-parse HEAD
git log --oneline -5

若部署的 SHA 早于修复 commit → 用户访问的是旧构建,修复根本没上线。

Step 3:检查 CI/CD 流水线状态

gh run list --limit 5

确认有没有挂起或失败的 deploy 阻塞了新版本落地。Next.js App Router、Vite 等框架的 API route handler 修改后通常需要重启 dev server,热更新并不覆盖服务端路由。

Step 4:按结果决定下一步

| git status | 部署 SHA | 行动 | |---|---|---| | 有未提交文件 | — | commit → push → 部署,重测 | | 干净 | 早于修复 commit | 查 CI,推部署,重测 | | 干净 | 等于 HEAD | 修复已上线但症状还在 → 此时再诊断才有意义 |

只有第三行才值得启动新一轮根因排查。

正解:拆开「已完成」的三个阶段,按图索骥

在每次"开发说好了 / 测试说没好"的对话后,先机械地跑 git status + 比对构建 SHA + 查 CI 状态,把这三步作为前置检查。通过了才进入重新诊断流程,省掉大量在错误前提上的推理。

预防

  • 开发的"已完成"报告末尾必须附 git status 输出,把未暂存的变更摊在明面上。
  • 线上页面统一暴露构建戳(commit SHA + 日期),方便测试截图、方便排查直接比对。
  • 把"done"拆成三句话:「代码已写完」「已 commit/push」「已部署到 XXX 环境」——每一句单独确认。

一句话外卖

开发和测试同时"都对"却结论相反,十有八九是他们在看不同的代码版本;先查 git status 和构建 SHA,两分钟排除部署断层,比再派一轮诊断 agent 划算得多。