最糟的 AI 编码会话,不是”AI 改错了一处”。是它在 12 个文件里改错了 47 处,你点了”Restore Checkpoint”,却发现 checkpoint 没抓到 agent 用一句 rm 在 bash 步骤里删掉的那三个文件。截至 2026 年 6 月,Cursor、Claude Code、GitHub Copilot 都内置了 checkpoint。它们做快速撤回很好用,也都有同样的盲区。这篇讲清楚:内置 checkpoint 到底做什么、在哪儿会悄悄失效,以及无论你用哪个工具都能让每次 AI 改动可逆的 git 四步纪律。
一句话总结
- 内置 checkpoint 是本地撤回,不是备份。 它存在你机器上、和 git 分开,而且(三大工具都一样)不追踪
rm、mv、cp这类 bash 命令改过的文件。 - git 才是真正的安全网。 四步纪律:AI 跑前 commit 一个干净基线、AI 输出 commit 前先审
git diff、长任务步骤间 commit、“可能还要”的改动用git stash。 - 高风险 run 前先 push。 本地 commit 和本地 checkpoint,机器或 repo 一坏就都没了。自主 agent 跑前先把基线 push 上去。
- 每次会话多花 2-3 分钟。 换来的是”撤回”永远成本低、永远不靠猜。
内置 checkpoint:每个工具到底做什么
过去一年里主流 AI 编码工具都加了 checkpoint 式的撤回。高层逻辑一样——在每次 AI 操作前给文件状态拍快照——而且它们都明确告诉你:真正的版本历史还得用 git。
| 工具(截至 2026 年 6 月) | 怎么回退 | 抓什么 | 保留多久 |
|---|---|---|---|
| Claude Code | /rewind,或空输入框连按两次 Esc | 每条用户 prompt 一个 checkpoint;可恢复代码、对话或两者 | 跨会话保留;30 天后自动清理(可配) |
| Cursor | 在 chat 时间线点 checkpoint,或在历史请求上点 “Restore Checkpoint” | 每次重要 Agent 改动前拍快照 | 当前会话 + 近期历史,自动清理 |
| GitHub Copilot(VS Code) | chat 里点 “Restore Checkpoint”;用 chat.checkpoints.enabled 开关 | 每个请求一份工作区 + 对话历史快照 | 仅当前会话 |
Claude Code 最细:它的 rewind 菜单能选 Restore code and conversation、Restore conversation(保留当前代码)、Restore code(保留对话)——想撤掉改动但留住聊天上下文时很有用。Cursor 和 Copilot 把代码和对话绑在一起回退。
所有内置 checkpoint 共有的三个缺口
这些限制都是厂商自己文档里写的,也正是 git 纪律仍然重要的原因:
- bash 命令的改动抓不到。 Claude Code 文档直说:
rm、mv、cp改过的文件”无法通过 rewind 撤回”。如果 agent 跑了一句碰文件的 shell 命令,checkpoint 不会帮你恢复。Cursor 和 Copilot 对非编辑工具的改动也一样。 - 只存本地、和 git 分开。 Cursor 把 checkpoint”存在本地,且和 Git 分开”。你笔记本一坏,换台机器
git clone出来零个 checkpoint。它们不是备份。 - 手动改和并发会话会漏。 checkpoint 一般只追踪当前会话里 AI 做的改动。你自己的手改、或同一 repo 上第二个 agent 会话的改动,往往抓不到。
内置 checkpoint 当成快速的”哎呀撤回上一步”来用。真正怕丢的东西全交给 git。
git 四步纪律
还是你熟悉的 git,只是节奏更严——因为 AI 改文件比你快、比你多。
- AI 跑前先 commit。 哪怕一个 “WIP” commit 也行——目的是 AI 改动出现后 diff 是干净的。
git commit -am "wip: baseline before AI refactor of userService"。 - AI 跑完,commit 前一定先
git diff。 逐行看你没要求的改动:被删的错误处理、被去的 null check、被改的 export 名、“优化”后语义微变的循环。这一步人人爱跳、事后人人后悔。 - diff 干净就带描述性 message commit。
git commit -am "ai: refactor callbacks to async/await in userService"。如果大部分好、少部分坏,用git add -p只 stage 好的,commit,剩下的用git restore <files>弃掉。 - 多步 agent 任务,强制步骤间 commit。 告诉 agent:“每个 ticket 停一下,我 commit 后你再继续。” 长自主 run 没有中间 commit,就是 4 小时灾难的来源。
AI 出的”可能还要、当下不要”的改动,用 git stash push -m "ai: 抽出 helper, 可能复用"。agent run 跑偏时直接 abort,再 git reset --hard HEAD 回到上次 known-good——比从 40 处乱改里手剥 bug 便宜得多。
按任务类型定 commit 节奏
| 场景 | 最低 commit 节奏 |
|---|---|
| 单个 AI 建议(一个函数、一个文件) | 每个接受的建议 1 commit |
| 跨文件重构 | 每个逻辑单元 1 commit(按模块 / 按关注点) |
| 自主 agent run | 每 3-5 步 1 commit,跑前再 push 一次 |
| 过夜 / 长批量 run | 先 push 基线;每个 checkpoint 都 commit + push |
开始前:AI 前 checklist
- working tree 干净。
git status没有未提交内容。手头进行中的先 stash 或 commit,让 AI 改动落在干净 diff 上。 - 当前状态测试绿。 你需要一个 known-good 基线。如果测试本来就红,你分不清是不是 AI 改坏的。
- commit 节奏定好。 见上表。默认”比你觉得需要的还多 commit 几次”。
- 基线已 push。 一周没 push 了 agent 又跑炸 repo,丢的工作没有任何 checkpoint 救得回。先 push。
每次会话前可粘的一句:“tree 干净、基线已 commit、基线已 push、测试绿。“
第一次实操怎么跑
- 选一个你平时随手让 AI 做的小任务——跨模块改函数名、抽 helper。
- 走完整纪律:干净 tree、基线 commit、基线 push、AI 跑、
git diff审、选择 stage、commit。 - 跟你平时”直接让它改”对比计时。开销很小(2-3 分钟);安全收益大。
- 第二次故意接受一个坏建议,再练回滚。
git reset和git restore是你想在压力来临前就练成的肌肉记忆——而不是等线上 agent 第一次翻车时才现学。
容易踩的坑
- 把内置 checkpoint 当备份。 它只存本地、还漏 bash 改动。怕丢的东西要 commit 加 push。
- 脏 tree 跑 AI。 你分不清自己在改的和 AI 改的。先 stash。
- 长 agent run 没有中间 commit。 出问题(一定会)就丢几小时工作或剥乱麻。
- “看着行,全 commit”不审 diff。 AI 的静默改动——删错误处理、删 guard——就这么上线了。
- 一个巨大 final commit。 出回归时
git bisect直接没用。每个逻辑步骤一 commit。 - 高风险 run 前没 push。 本地 commit 不算备份;agent 把 repo 搞坏能让你全丢。
常见问题
- 工具有 checkpoint 了我还需要 git 吗?: 需要。Cursor 和 Claude Code 文档都说 checkpoint “补充而非替代”版本控制。checkpoint 是本地撤回;git 是可 push 的永久历史。
- agent 删了个文件,rewind 没找回来,为什么?: 它几乎肯定用的是 bash 命令(
rm)而不是文件编辑工具。内置 checkpoint 不追踪 bash 改过的文件。如果之前 commit 过,用git checkout HEAD -- <file>找回。 - 能用
git stash代替 commit 吗?: 短期藏行。长 run 的检查点用 commit 更稳——stash 容易丢,也不会 push 到 remote。 - 巨大的 AI diff 怎么高效审?: 先
git diff --stat看文件图,再逐文件git diff <file>。先扫”意外文件”——它们暗示 agent 引入的 scope 漂移。 - IDE undo(Ctrl+Z)呢?: 单点改可以,多文件 agent run 没用,关掉编辑器就没了。git 才是唯一可信源。
- 能脚本化吗?: 能。团队常用一个
pre-ai.sh,跑git status; git diff --stat,脏 tree 就拒绝继续。git restore的确切语义见 git 官方文档。