用 Codex 完成一次小修改:需求、范围、执行、验证、回滚
从一次很小的文件修改开始,练习四件事:把需求说清楚、限制执行范围、读懂实际变更、恢复到已知基线。做完后,你应该能用证据说明“改了什么”和“哪些文件没动”。
核验日期:2026-10-13(Asia/Shanghai)。本篇由本次 Codex Agent 在 Windows / PowerShell / Git 2.55.0.windows.3 环境完成独立演示。这里公开的是这一次运行记录;你的系统、权限和工具版本仍需自行核对。
适合谁,开始前准备什么
- 已经拥有 Codex 使用权限,想让 Agent 做第一次文件修改的 Windows 用户。
- 准备一个自己有权读写的空练习父目录;只让 Codex 访问本次练习,不包含业务文件或个人资料。
- PowerShell 能执行
git --version;能查看 UTF-8 文本,愿意逐项核对执行结果。
本练习只需要现有的 Codex 文件操作能力和本地 Git,不需要填写 API 密钥、安装 Notebook 或另外调用付费模型。Codex 是否可用以你账户和当前工具的实际状态为准。
官网的标题、教程正文和商品说明仍通过 WordPress / WooCommerce 原生后台维护。下面编辑 README 是为了练习 Agent 的执行边界,并不是官网日常改字的必要步骤。
OpenAI 官方文档建议先明确一个小范围的任务约定,再做有针对性的修改,并用实际验证结果决定下一步。我们把这个思路用于一份 README,同时保留前后内容和验收记录;参考 OpenAI Docs:Build iterative repair loops with Codex。
第一步:建立独立练习目录
在自己选定的空练习父目录打开 PowerShell。下面的 .local\qa\first-task-demo 是练习相对路径;代码先核对绝对目标落在该 QA 目录内,再拒绝覆盖已有目录。以下保留本次实际执行的关键命令,记录文件的保存操作已省略,父目录用当前位置表示。
$ErrorActionPreference = 'Stop'
$repoPath = (Get-Location).Path
$qaRoot = [IO.Path]::GetFullPath((Join-Path $repoPath '.local\qa'))
$demoPath = [IO.Path]::GetFullPath((Join-Path $qaRoot 'first-task-demo'))
if (-not $demoPath.StartsWith(
$qaRoot + [IO.Path]::DirectorySeparatorChar,
[StringComparison]::OrdinalIgnoreCase)) {
throw 'Practice target is outside QA directory.'
}
if (Test-Path -LiteralPath $demoPath) {
throw 'Practice target already exists; preserve it and use a new directory.'
}
[IO.Directory]::CreateDirectory($demoPath) | Out-Null
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
在同一 PowerShell 窗口继续写入两个练习文件。README 是唯一允许改的目标;GUARD 用来确认范围限制是否兑现。
$beforeReadme = "# 第一次小修改练习`n`n这是一个独立的 README 编辑练习。`n"
$guardText = "GUARD: this file must remain unchanged.`n"
[IO.File]::WriteAllText((Join-Path $demoPath 'README.md'), $beforeReadme, $utf8NoBom)
[IO.File]::WriteAllText((Join-Path $demoPath 'GUARD.txt'), $guardText, $utf8NoBom)
Set-Location -LiteralPath $demoPath
git --version
git init -b main
if ($LASTEXITCODE -ne 0) { throw 'git init failed.' }
$actualRoot = (& git rev-parse --show-toplevel | Out-String).Trim()
if ($LASTEXITCODE -ne 0 -or [IO.Path]::GetFullPath($actualRoot) -ne $demoPath) {
throw 'Git root is not the isolated practice directory.'
}
第二步:保存基线,记住恢复依据
先提交原始练习文件,再记录提交 ID 和两个文件的 SHA256。这里的姓名与邮箱是演示身份,git -c 仅作用于这一次命令,不会写入你的全局身份配置。换到真实项目时,应使用项目要求的提交身份。
git -c core.autocrlf=false add -- README.md GUARD.txt
if ($LASTEXITCODE -ne 0) { throw 'git add failed.' }
git -c core.autocrlf=false -c user.name='Codex Demo' -c user.email='codex-demo@example.invalid' commit --no-gpg-sign -m 'baseline: isolated first task'
if ($LASTEXITCODE -ne 0) { throw 'baseline commit failed.' }
$baselineCommit = (& git rev-parse HEAD | Out-String).Trim()
if ($LASTEXITCODE -ne 0) { throw 'baseline lookup failed.' }
$readmeBeforeHash = (Get-FileHash -LiteralPath README.md -Algorithm SHA256).Hash
$guardBeforeHash = (Get-FileHash -LiteralPath GUARD.txt -Algorithm SHA256).Hash
git status --porcelain
预期:提交成功,最后一条命令没有输出。保留 $baselineCommit 和两个哈希;后续在同一窗口执行。若关掉了窗口,先从自己的记录重新取得变量,不能直接照抄本文演示提交 ID。
第三步:给 Codex 一段有边界的提示词
核对 Codex 当前工作目录是刚刚建立的独立练习仓库;不能确认时,先只读查看路径。把下面这段提示词发给有权操作该练习目录的 Codex 会话。没有文件访问权限的会话需要先解决权限,不能把一段建议当成已执行修改。
只在本次已核对的独立练习目录 .local/qa/first-task-demo 工作。先读取 README.md 和 GUARD.txt。
只改 README.md:标题“第一次小修改练习”改成“用 Codex 完成第一次小修改”;描述“这是一个独立的 README 编辑练习。”改成“这个练习只修改 README.md,并通过 diff 与哈希验收。”。保留空行及其余内容。
禁止修改 GUARD.txt、创建其他文件、删除文件、修改任何 Git 配置、提交或推送。禁止进入主项目改文件。不要调用 API 或额外的模型服务。
修改后运行 git diff -- README.md、git diff --name-only、git diff --check,核对 GUARD.txt 的 SHA256 与基线一致。报告实际结果,先保留变更供阅读;恢复由下一步独立执行。
这段提示词包含目标、允许修改的文件、禁止动作和验收办法。它降低误解的机会,但是否守住范围,仍要看下一步实际 diff 和文件哈希。
第四步:看 diff,再判断是否符合要求
git -c core.autocrlf=false diff -- README.md
git -c core.autocrlf=false diff --name-only
git -c core.autocrlf=false diff --check
Get-FileHash -LiteralPath README.md -Algorithm SHA256
Get-FileHash -LiteralPath GUARD.txt -Algorithm SHA256
git status --porcelain
本次实际 diff 如下:减号是原文,加号是改后文字。diff --name-only 只输出 README.md,diff --check 没有输出且退出码为 0。
diff --git a/README.md b/README.md
index 1a4a21f..6820ffe 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,3 @@
-# 第一次小修改练习
+# 用 Codex 完成第一次小修改
-这是一个独立的 README 编辑练习。
+这个练习只修改 README.md,并通过 diff 与哈希验收。

第五步:按验收条件逐项检查
- README 的标题和一句描述与提示词一致,空行和其余内容保留。
- 变更文件列表只有 README.md;还要查看
git status --porcelain,确认没有未跟踪新文件或已暂存改动。 - GUARD 的 SHA256 与基线相同;
diff --check退出码为 0。 - 执行记录能交代命令、结果和时间,不能只写“看起来正常”。
| 本次检查项 | 实际结果 |
|---|---|
| 基线提交 | 0f93dcd4390417bc6fbafe79dde009e743be1a2c |
| 变更范围 | 只发现 README.md 的预期两行变更;GUARD 未变 |
| 格式检查 | git diff --check 退出码 0 |
| 修改核验时间 | 2026-10-13 01:31:26 +08:00 |
| 恢复核验时间 | 2026-10-13 01:32:16 +08:00;README、GUARD 哈希与基线相同,工作树 clean |
SHA256 用于比较文件字节是否一致;它不能证明一段代码的业务逻辑正确。这里是文本练习,所以还必须读 diff,核对文字。真实功能修改要补上与功能相关的执行检查。
第六步:只恢复本练习的 README
先保存自己需要的 diff 或改后副本到练习仓库以外。本次前后文件与记录已保存,练习仓库和基线提交保留。然后核对当前 Git 根目录,使用自己记录的基线提交,只恢复 README.md。该操作会覆盖这份练习 README 的未提交修改。
$actualRoot = (& git rev-parse --show-toplevel | Out-String).Trim()
if ($LASTEXITCODE -ne 0 -or [IO.Path]::GetFullPath($actualRoot) -ne $demoPath) {
throw 'Restore target is not the isolated practice repository.'
}
git cat-file -e ($baselineCommit + '^{commit}')
if ($LASTEXITCODE -ne 0) { throw 'Recorded baseline is not a commit.' }
git -c core.autocrlf=false restore --source=$baselineCommit -- README.md
if ($LASTEXITCODE -ne 0) { throw 'Targeted README restore failed.' }
$readmeRestoredHash = (Get-FileHash -LiteralPath README.md -Algorithm SHA256).Hash
$guardRestoredHash = (Get-FileHash -LiteralPath GUARD.txt -Algorithm SHA256).Hash
$readmeRestoredHash -eq $readmeBeforeHash
$guardRestoredHash -eq $guardBeforeHash
git status --porcelain
预期:两个比较都输出 True,最后一条命令没有输出。本次也实际得到这一结果。恢复命令只在独立练习仓库执行;不要把它改成对整个工作目录的回退命令。
常见问题
提示“git 不是内部或外部命令”
当前 PowerShell 找不到 Git。先确认自己的 Git 安装和命令路径,再运行 git --version。本篇没有核验你的安装状态,不能据此判断已经安装成功。
练习目录已存在,或者 Git 根目录不一致
立即停止这次写入或恢复。保留原目录,换一个新的练习目录并同步修改路径;不要删除已有练习来硬套步骤。Git 根目录必须是这次独立练习目录。
Codex 只给了建议,没有改文件
先核对会话是否具有这份练习的文件访问与执行权限。权限和实际执行方式不确定时先只读检查;只有文件内容、diff 和命令结果发生预期变化,才算本次修改已执行。
diff 多了文件,或哈希不一致
先看 git status --porcelain,区分已暂存、未暂存和未跟踪文件;再检查是否有编辑器改了编码或换行。本演示用 UTF-8 无 BOM 和 LF,并在关键 Git 命令使用 -c core.autocrlf=false。不要为了让检查通过而删除其他文件或重新生成基线。
下一步
先读一遍动手前检查清单,把目标、输入、验收和回滚依据写齐。然后回到Codex 与自动化路线完成自测;能解释这次 diff 和恢复依据,再扩大任务范围。