Skip to main content

用途

这一页解决一个很具体的问题:Codex 已经改完代码,接下来怎样确认改动正确,怎样测试,怎样在失败时止损。 核心顺序只有一句话:
先保护现场,再看 diff;先测最小路径,再扩大测试;确认无误后才 commit;没有明确授权就不 push。
本页不把“模型说完成了”当成完成标准。 完成标准必须有证据:
  • 你知道当前所在目录和分支。
  • 你知道哪些文件被改了,以及每个文件为什么被改。
  • 你有一组与改动相匹配的测试结果。
  • 失败时能判断是代码、环境、测试还是数据问题。
  • 你能只撤销 Codex 的改动,不误伤自己的未提交工作。
  • 你能解释为什么允许 commit,以及为什么暂时不 push。
命令、参数和 Codex 界面会随版本变化。 遇到差异时,以本机 codex --help、会话中的 /help、项目测试脚本和官方文档为准。 参考资料包括 参考/codex/06-first-task.md、参考/codex/15-permissions.md、参考/codex/26-git-github.md 和 参考/codex/35-cheatsheet.md。

01 先保护当前工作

先确认路径

不要在不知道当前目录的情况下执行恢复命令。
Windows PowerShell 可以使用:
预期结果类似:
如果 git rev-parse --show-toplevel 报错,当前目录不是 Git 仓库。 先不要让 Codex 批量修改,先回到正确项目目录,或明确建立 Git 仓库。

记录基线

在任务开始前保存一份基线信息。
工作区干净时,git status --short 没有输出。 有输出时,先把每一行的含义弄清楚,再决定是否继续。 例如:
这表示 src/cart.ts 有未暂存修改,notes/try.txt 是未跟踪文件。 它们可能是你自己的工作,不一定是 Codex 产生的。

未提交变更保护原则

如果开始任务前已经有未提交变更,默认不要直接让 Codex在同一工作区大范围修改。 更稳妥的选择有三种:
  1. 先保存当前变更,再开始新任务。
  2. 从当前状态建立临时分支,把任务隔离开。
  3. 使用新的 git worktree 或临时副本。
不要为了得到“干净状态”而直接运行:
也不要随意运行:
前者会丢弃已跟踪文件的未提交改动,后者会删除未跟踪文件。 两者都不是普通的“清理一下”。

先保存补丁

如果已有修改,但暂时不能 commit,可以先导出补丁。
预期:上级目录出现补丁文件。 补丁不是完整备份,未跟踪文件不会自动进入 git diff。 需要保护未跟踪文件时,先单独复制或使用压缩备份。
Windows 可以直接复制到项目外目录:

建立检查点

如果当前修改已经确认是应该保留的工作,可以提交一个明确的检查点。
预期结果类似:
检查点的目的不是发布功能,而是让你拥有一个已知可恢复位置。 提交信息要说明用途,不要使用含糊的 update 或 test。 如果当前未提交工作混杂了别人的内容,先不要替别人 commit。 应先询问负责人,或建立副本、worktree,再继续。

02 让 Codex 在可控范围内工作

启动 Codex 前,明确任务的文件范围、测试命令和禁止事项。 可以直接使用下面的提示词:
对陌生项目,先使用只读或较严格的权限模式。
确认理解范围后,再按项目实际需要使用工作区可写模式:
进入会话后可以查看状态:
参考输出可能包含:
本地开发通常保持 workspace-write 加 on-request。 不要在宿主机日常项目中使用 --yolo 或完全访问模式。 联网、安装依赖、访问工作区外目录、发送外部请求,必须单独确认。

03 先看总览 diff

Codex 完成一次修改后,第一件事不是 commit,而是查看工作区状态。
三条命令分别回答:
  • 哪些文件处于修改、新增、删除或重命名状态。
  • 每个文件改了多少行。
  • 文件的状态变化是什么。
预期示例:
注意:git diff --stat 默认不统计未跟踪文件的内容。 所以看到 ?? 时,必须打开该文件逐行检查,不能只看 stat。

使用 /diff

在 Codex 交互会话中,可以输入:
这通常用于快速查看当前 Git 差异。 不同版本是否显示未跟踪文件、显示方式和菜单名称可能不同。 终端中的 git diff 仍然是可靠的本地依据。

查看完整未暂存 diff

这里关闭外部 diff 工具,避免输出被第三方程序改变。 需要查看暂存区差异时使用:
需要比较某个检查点和当前工作区:
需要只看某个文件:
需要查看某一段上下文更多的差异:

预期 diff 示例

阅读时记住:
  • - 是旧内容。
  • + 是新内容。
  • 没有前缀的行只是上下文。
  • @@ -8,7 +8,15 @@ 表示修改附近的行号范围。
  • 文件头部的 a/ 和 b/ 是 Git 的旧路径和新路径。

04 按文件审查,而不是只看总结

总览 diff 只能发现范围异常。 真正的审查要逐文件完成。 建议顺序如下:
  1. 配置和依赖文件。
  2. 业务逻辑文件。
  3. 数据库、迁移和接口文件。
  4. 测试文件。
  5. 文档、生成文件和临时文件。

第一问:文件是否在允许范围

把实际文件列表和任务中的范围逐一对照。
预期只出现计划内文件。 如果任务只要求改 src/cart.ts,却出现:
应先暂停。 逐项确认这些文件是否确实由依赖、配置或测试要求产生。 不清楚原因时,不要为了“让 diff 变干净”直接删除文件。 先让 Codex 解释,或手动检查生成原因。

第二问:每处修改是否服务于需求

逐段阅读新代码,问自己:
  • 这几行解决了哪个验收条件?
  • 是否加入了未要求的重构?
  • 是否改变了公共接口、错误类型或返回格式?
  • 是否改变了日志、权限、缓存或事务行为?
  • 是否把用户输入直接送进命令、SQL 或 HTML?
任何无法解释的新增依赖、网络请求、环境变量或权限变更,都应列为阻塞项。

第三问:删除是否有理由

删除行比新增行更值得警惕。 重点查看:
  • 异常处理是否被删掉。
  • 鉴权和权限检查是否被绕过。
  • 超时、重试、事务回滚是否被删掉。
  • 测试夹具、锁文件和配置是否被删掉。
  • 注释删除后是否失去关键约束。

第四问:输入和边界是否仍然成立

至少检查以下输入:
  • 空值、空数组和缺失字段。
  • 类型错误和超大数值。
  • 重复请求和并发请求。
  • 未登录用户和无权限用户。
  • 超时、断网、服务端 4xx 和 5xx。
  • 旧数据、脏数据和数据库迁移前的数据。

第五问:测试是否真的覆盖改动

新增一个测试文件不代表覆盖了新逻辑。 打开测试代码,确认它断言了行为,而不是只断言函数“能运行”。 例如下面的断言有实际意义:
而下面的测试可能过于空泛:
如果 item 是无效输入,这个测试反而可能掩盖问题。

05 逐文件审查命令

只审一个业务文件

预期:只输出 src/cart.ts 的未暂存修改。

只审一个测试文件

查看新增文件

未跟踪文件不会出现在普通 git diff 内容中。 先查看文件状态:
再用项目已有工具或直接打开文件检查。 如果要让 Git 显示新增文件的完整差异,可以先只暂存这个文件:
--intent-to-add 会让 Git 知道路径,但不把完整内容放进暂存区。 不确定时先看状态,避免把整个目录暂存。

显示空白问题

预期:没有输出且退出码为 0。 如果看到类似:
先修复空白,再继续审查。

检查已暂存内容

当你准备分批提交时,使用:
每个代码块逐一选择 y、n 或 s。 然后查看:
预期暂存区只含准备提交的部分。

06 测试矩阵:让测试和风险对应

不要只写“已测试”。 把修改映射到测试层级,并记录实际命令和结果。 命令必须以项目实际脚本为准。 先查看 package.json、pyproject.toml、Makefile 或项目 README,不要凭记忆编造命令。

一个最小测试矩阵示例

假设本次修改是“购物车合并重复商品”。

测试顺序

先运行便宜且能快速定位的检查:
再运行耗时检查:
预期结果可能是:
以及:
不要把“命令返回成功”误认为所有风险都已覆盖。 检查命令是否真的执行了目标测试,是否因为配置、筛选器或缓存而跳过。

07 失败分类:先判断,再修复

测试失败时不要立刻让 Codex“大改一遍”。 先保存完整输出:
PowerShell 可以使用:
然后按类别分类。

A 类:代码逻辑失败

特征:断言结果与预期不符,堆栈指向本次改动。 例子:
处理方式:
  • 找到第一个失败断言。
  • 对照 diff 检查状态更新和边界条件。
  • 补充一个能复现失败的测试。
  • 只修复相关逻辑,再重跑同一测试。

B 类:类型或静态规则失败

特征:编译器、lint 或类型检查报错,通常在测试运行前出现。 例子:
处理方式:
  • 检查接口变更是否超出需求。
  • 不要用 any、禁用规则或忽略错误来掩盖问题。
  • 确认所有调用方和测试已同步更新。

C 类:环境或依赖失败

特征:找不到命令、端口被占用、依赖下载失败、运行时版本不匹配。 例子:
处理方式:
  • 记录 Node、Python、数据库和工具版本。
  • 先确认依赖是否按项目说明安装。
  • 不要未经确认升级锁文件或全局工具。
  • 环境问题解决后,重新运行原命令。

D 类:测试数据或服务失败

特征:连接数据库、外部 API、认证服务或测试容器失败。 例子:
处理方式:
  • 确认使用的是测试服务,不是生产服务。
  • 检查测试账号和最小权限凭据。
  • 不要把真实令牌写入代码、日志或提交。
  • 将“未执行”与“失败”分开记录。

E 类:基线或测试本身失败

特征:修改前同一测试就失败,或测试断言与当前需求矛盾。 处理方式:
  • 在检查点上复跑同一命令。
  • 用 git show HEAD:path/to/file 检查基线内容。
  • 记录“基线已失败”,不要把旧问题算到本次改动上。
  • 修改测试前先确认需求和团队约定。

失败后的提示词


08 测试失败时的事故止损

当失败范围不明时,先停止 Codex 的后续修改。 可以按 Esc 中断当前动作,或关闭会话中的自动继续流程。 然后执行:
保存三类信息:
  • 最后一次成功的测试命令。
  • 第一个失败的命令和完整输出。
  • 失败发生前后的 diff。
如果程序正在运行并可能影响外部服务,立即停止本地进程。 不要继续点击重试,尤其是支付、写库、发消息和部署操作。 如果可能已经触及共享环境:
  1. 记录时间、命令、分支和请求编号。
  2. 立即通知负责人或值班人员。
  3. 暂停进一步发布和推送。
  4. 检查是否产生重复写入或外发数据。
  5. 使用服务自身的撤销、备份或补偿流程。
Git 只能恢复文件和提交历史,不能撤回已经发送的邮件、已经执行的数据库写入或已经发布的版本。

09 未提交改动的回滚

回滚前先保存证据,再决定范围。

回滚单个文件

确认该文件的所有未提交修改都属于本次任务后,才使用:
预期:该文件恢复到 HEAD 版本,其他文件不变。 再次检查:

回滚多个指定文件

路径必须明确,不要在不清楚范围时使用 .。

回滚全部未暂存改动

这会丢弃所有已跟踪文件的未暂存修改。 执行前必须确认:
  • 当前目录正确。
  • 没有同事的未提交工作。
  • 已导出补丁或已有检查点。
  • 未跟踪文件不需要保留。
它不会自动删除未跟踪文件。

取消暂存但保留文件修改

如果只是误把文件放进暂存区:
预期:文件从暂存区移除,但工作区内容仍保留。 同时取消暂存并恢复内容:
这条命令会同时丢弃该文件的暂存和工作区修改,使用前必须再次核对路径。

未跟踪文件的处理

git restore 不会恢复或删除未跟踪文件。 先查看:
确认文件确实是本次生成且不需要后,才可以单独删除。
Windows PowerShell:
不要使用 git clean -fd 作为第一反应。

10 已提交改动的回滚

已经 commit 的改动不应靠删除提交来“假装没发生”。 共享分支上,优先创建新的反向提交。

查看要撤销的提交

预期:先确认提交 SHA、作者、文件和改动内容。

使用 git revert

预期:Git 创建一个新的提交,内容抵消指定提交。 如果打开编辑器,保留默认的 revert 信息,或写清原因。 然后检查:

处理 revert 冲突

如果提示冲突,不要继续提交半成品。
解决冲突后:
如果确认不应继续:
预期:回到 revert 开始前的状态。 git revert 适合已经进入共享历史的提交。 不要对共享分支使用 git reset --hard 配合强制推送来改写历史。

11 checkpoint 与临时分支

什么时候建立 checkpoint

以下情况建议在任务前建立检查点:
  • 将修改多个业务文件。
  • 会改依赖、配置或数据库迁移。
  • 任务可能需要多轮试错。
  • 需要让 Codex 运行自动修复。
  • 你无法快速判断改动是否正确。
检查点可以是一个本地 commit,不代表要 push。
预期:当前分支多一个明确的本地提交,工作区回到干净状态。

使用临时分支

旧版本 Git 可使用:
建议分支名包含任务主题,不要使用 test 这种无法追踪的名称。 确认分支:
预期:当前分支为 codex/cart-validation。 在临时分支完成修改、测试和审查。 满意后再由人决定是否合并或开 PR。

使用 worktree 隔离

如果主工作区有未提交工作,可以创建新的 worktree:
预期:新目录位于独立分支,原目录的未提交文件不被改变。 任务结束后,先确认分支已合并或不再需要,再移除 worktree:
不要在仍有未保存工作时移除 worktree。

12 何时允许 commit

commit 是保存一组经过审查的历史,不是“让 Codex 停止输出”的按钮。 满足以下条件后才允许 commit:
  • 路径和分支确认无误。
  • git status 中没有意外文件。
  • 已查看总览 stat 和完整 diff。
  • 已按文件解释每个新增、修改和删除。
  • git diff --check 通过。
  • 与改动对应的测试已运行并记录结果。
  • 失败项已修复,或得到明确的豁免说明。
  • 没有密钥、令牌、个人数据和临时产物。
  • 没有把生成物、缓存和日志误加入。
  • commit 不包含与任务无关的工作。
提交前再次检查:
然后精确暂存:
最后再提交:
预期:commit 只包含已审查的两个文件。 如果 git diff --cached 里出现无关文件,先取消暂存:
不要用 git add . 代替逐项审查,尤其是仓库中存在日志、构建产物或本地配置时。

13 如何避免误推送

commit 和 push 是两个不同决定。 本地 commit 只是写入当前仓库历史。 push 会把提交发送到远端,可能触发 CI、部署和通知。

推送前确认三件事

预期:你能说出当前分支、远端仓库和将要发送的提交。 查看远端差异:
如果当前分支不是明确的任务分支,暂停推送。 如果本来只想开 PR 分支,却发现当前是 main,不要直接 push。

使用 dry-run

预期:Git 显示将更新哪个远端分支,但不会真正发送对象。 --dry-run 不能代替实际审查,它只验证推送计划。

防止推错分支

推送时明确写出源分支和目标分支:
只有明确授权后,才考虑推送到指定远端。 不要把 git push 交给未经审查的自动流程。 尤其不要使用:
--force-with-lease 比强推更能避免覆盖新提交,但仍会改写远端历史,不能作为日常默认。 主干、保护分支和团队仓库应遵守项目的 PR 流程。 合并、发布和生产部署都应由负责人明确放行。

推送后确认

推送完成后检查:
再到远端页面确认分支和提交号一致。 推送超时不要马上重复执行。 先查询远端:
这样可以避免第一次其实成功、第二次又重复操作。

14 一次完整演练

下面是一条适合第一次练习的闭环。

第一步:确认并保存检查点

预期:位于新分支,工作区干净。

第二步:提出范围明确的任务

第三步:查看文件范围

预期只有计划中的业务文件和测试文件。

第四步:按文件检查

确认测试覆盖正常输入、重复输入和非法输入。

第五步:运行矩阵中的检查

如果通过,继续运行项目要求的类型检查或构建。 如果失败,先保存日志并按失败分类,不要直接提交。

第六步:决定保留或回滚

逻辑正确、测试通过:保留工作区,准备暂存。 逻辑错误且整轮都不要:
只有某个文件错误:只恢复那个文件。

第七步:精确 commit

第八步:停止在本地

如果用户没有明确要求推送,流程在本地 commit 结束。 输出提交号、测试命令和未验证项,等待下一步授权。

15 验收清单

提交或交给同事审查前,逐项打勾:

工作区与保护

  • 我确认了项目根目录。
  • 我确认了当前分支。
  • 我知道任务开始前是否已有未提交变更。
  • 重要任务已有 checkpoint、补丁或独立 worktree。
  • 我没有使用未经确认的 reset --hard 或 clean -fd。

Diff 审查

  • 我看过 git diff --stat。
  • 我看过 git diff --name-status。
  • 我按文件查看了完整 diff。
  • 我检查了新增文件,而不只依赖 git diff。
  • 每一处修改都能对应需求或测试。
  • 删除、依赖、配置和权限变化都有明确理由。
  • git diff --check 通过。

测试

  • 我运行了格式或空白检查。
  • 我运行了相关 lint 或类型检查。
  • 我运行了直接相关的单元测试。
  • 需要时运行了集成测试、构建和手工冒烟。
  • 我记录了命令、结果和测试环境。
  • 我区分了失败、跳过、未执行和环境阻塞。

回滚与提交

  • 我知道未提交改动如何用 git restore 恢复。
  • 我知道已提交改动如何用 git revert 撤销。
  • 我没有把别人的未提交修改一起提交。
  • 暂存区只包含本次任务文件。
  • commit 信息能说明实际变更。
  • 没有密钥、令牌、.env、个人数据、日志和缓存。

推送边界

  • 用户明确要求了 push,或项目流程明确授权了 push。
  • 我确认了远端、目标分支和待推送提交。
  • 我执行过 git push --dry-run 或等价检查。
  • 我没有使用 --force。
  • 我没有让 Codex 自动合并主干或发布生产。
  • 推送后核对了远端分支和提交号。

小结

审 diff 不是看一眼绿色和红色,而是逐文件回答“为什么改、改对了吗、是否漏了边界”。 测试不是越多越好,而是要覆盖这次修改真正影响的路径。 失败不是一个笼统的“没通过”,应先区分逻辑、静态检查、环境、服务数据和基线问题。 未提交改动优先用精确路径的 git restore,已提交改动优先用新的 git revert。 复杂任务在改前建立 checkpoint 或临时分支,主工作区有个人修改时使用 worktree 隔离。 只有 diff、测试、敏感信息和范围都验收通过,才允许 commit。 没有明确推送授权时,commit 留在本地;推送前再次确认远端、分支和提交,绝不把 merge、发布或强推交给自动流程。 参考资料:参考/codex/06-first-task.md、参考/codex/15-permissions.md、参考/codex/26-git-github.md、参考/codex/35-cheatsheet.md。 动态信息以本地 codex --help、会话 /help、项目文档和官方文档为准。