用独立git worktree临时应用AI生成补丁并执行一条安全命令,验证通过再合并,避免只看diff就合并导致本地构建失败。
你一直在通过阅读 diff 来审查 AI 生成的补丁,但代价最高的失败很少是你能一眼看出来的那些。它们是那些能够顺利应用、通过你肉眼检查、然后在本地运行第一条命令时就坏掉的补丁。本指南为你提供一个只读的 git worktree 冒烟门,它在一个独立的目录中应用候选补丁,运行一条安全命令,执行完毕后丢弃该 worktree。你还会得到一个决策表,用于决定何时将同一条命令放到免费服务器选项上而不是你自己的笔记本上。
你从一个约束开始,它改变了你对待任何生成补丁的方式:diff 在被证明可用于实时 checkout 之前是一个不受信任的产物。阅读 diff 告诉你变更在语法上是否合理。在应用 diff 后运行命令告诉你该变更是否保持了你关心的那个行为。如果你跳过第二步,你就会交付未经测试的推理,然后在后续为不稳定的合并、坏掉的本地构建和紧急回滚付出代价。
当你在 MonkeyCode 上使用免费的模型访问时,同样的规则同样适用。生成补丁,将其保存为统一 diff 文件,然后将这个文件当作需要验证的补丁而不是直接合并的变更来处理。披露:本文作为 MonkeyCode 产品推广的一部分而撰写。免费服务器选项稍后作为独立运行器很有用,但不应从你自己的工作流中移除只读门。
你可能见过一个在代码审查中看起来正确、但运行时仍然失败的补丁。该变更移动了一个函数、更改了一个 import、或者编辑了一个 fixture,而 diff 本身并不包含测试命令会失败的任何迹象。diff 是变更的表示,而不是行为的证明。因此,对于任何生成的补丁,第一个要回答的问题不是"这看起来对吗?"而是"在我应用它之后还能运行吗?"
第二个失败模式是工作区污染。如果你在主工作树上应用补丁,运行一条测试,然后想继续编辑,你现在就把生成的变更和你自己进行中的工作混在一起了。你要么比预期更早提交,要么 stash,要么手动清理。一个可丢弃的 worktree 将这些状态分开,使得补丁在通过冒烟命令之前永远不会碰到你的分支。
你可以用一个小 shell 脚本实现这个门。该脚本接受一个补丁文件和一个测试命令作为参数。它从 HEAD 创建一个 detached worktree,在那里应用补丁,运行你的命令,然后在 trap 中移除 worktree。这使得即使命令失败,你的当前分支也不会被触及。
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -lt 2 ]]; then
echo "usage: $0 <patch-file> <test-command> [args...]" >&2
exit 1
fi
PATCH_FILE="$1"
shift
TEST_CMD=("$@")
WORKTREE_DIR=$(mktemp -d ".smoke-wt-XXXXXX")
trap 'git worktree remove --force "$WORKTREE_DIR"' EXIT
git worktree add --detach "$WORKTREE_DIR" HEAD
git -C "$WORKTREE_DIR" apply --check "$PATCH_FILE"
git -C "$WORKTREE_DIR" apply "$PATCH_FILE"
(
cd "$WORKTREE_DIR"
printf 'Running: %s\n' "${TEST_CMD[*]}"
"${TEST_CMD[@]}"
)
printf 'Smoke passed: %s\n' "$WORKTREE_DIR"
你通过补丁文件加一条命令来运行它。例如:
./smoke-gate.sh /tmp/candidate.patch pytest -q tests/unit
./smoke-gate.sh /tmp/model.patch npm test
重要的细节是脚本将测试命令作为数组接收,而不是作为单个字符串。这保留了 -q tests/unit 这样的参数,而不需要你构建一个 shell 字符串。你仍然不应该将不受信任的命令传入脚本;脚本信任你传入的命令。
你不需要为每个补丁都使用免费服务器。使用能够回答你一个问题的最轻量执行上下文。
你可以将此表附加到合并检查清单上,这样这个门就不会在截止日期压力下变成一种个人习惯然后消失。
如果你的账户可以使用 MonkeyCode 的免费服务器选项,将其作为同一冒烟命令的执行目标,而不是替代先打补丁规则的替代品。原则保持不变:将补丁应用到一个独立的副本,运行一条命令,观察结果。免费服务器在以下情况下有用:命令需要你不希望在本地运行的服务、你的笔记本已经很忙了、或者你想要一个可重复的环境来进行检查。
保持命令定义小而明确。一个有用的冒烟命令是在真正失败时以非零退出、并且不依赖交互式输入的命令。对于 Python 项目,pytest -q tests/unit 是一个合理的初步信号。对于 Node 项目,npm test -- --runInBand 比基于 watcher 的命令更好,因为后者永远不会退出。如果命令需要一个 secret,不要将其放在补丁文件中;通过执行环境注入。
worktree 冒烟门是一种初次的适用性检查,而不是完整的审查或 CI 流水线。它不能证明补丁是正确的、安全的或与系统设计一致的。它只证明在应用补丁后有一条命令通过了。
如果你的项目已经有严格要求任何分支在人工审查之前不能运行,如果你的仓库不能干净地支持多个 worktree,或者如果你的冒烟命令有可以逃逸出 worktree 的副作用,你应该跳过这种方法。写入系统目录、发送通知或修改共享数据库的测试即使在 worktree 是可丢弃的情况下仍然可能影响环境。在这些情况下,在容器内或专用免费服务器环境中运行检查,而不是在你的开发主机上。
你不需要一次采用所有步骤。提前决定你的冒烟命令是什么,并且在生成补丁在可丢弃的 worktree 中通过该命令之前,拒绝合并任何生成的补丁。这个习惯会超越你使用的任何模型或免费服务器而延续下去。如果第一次运行失败,将 worktree 保留足够长的时间来阅读失败的输出,然后在你记录结果后让 trap 清理它。