AI 删文件防御与 Git 兜底
下午让 Codex 给我写代码,遇到一个问题让它修复,我开始刷抖音,一抬头,AI 跟我说这个文件夹好像是空的,我一看我去,桌面上的文件都没了,我看一下 D 盘,直接给我清空了。
我写的论文,年后要发论文,没备份也没了。用恢复工具能扫描出来结构,能扫描出来文件大小,但是二进制全是 0,恢复之后不可打开。
太绝望了,提醒大家,用编程工具权限不要给那么高,也不会对你的数据负责。
相关 X 链接:
看完这类事故,很多人会立刻补两样东西:一条"不要用 rm"的规则,或者一个"反正还有 Git"的心理安慰。两样都不够,因为 trash、规则文件、Git、远程仓库、额外备份,本来就在不同层上工作。
这一篇只做一件事:把防护层和兜底层分开讲清楚。前者回答"怎样让模型少删",后者回答"删了之后怎么退"。两者都要有,顺序不能反。
第一层:将不可逆删除改为回收站删除
很多人第一反应是在 AGENTS.md 或 CLAUDE.md 里加一句:
删除文件时使用 trash,不要直接使用 rm。或者更激进一点,在 shell 里做别名:
alias rm='trash'这类做法当然有意义,但意义非常具体:把一部分"手滑式删除"改成可恢复的删除。如果模型老老实实照着你给的命令习惯走,它原本会直接删掉文件,现在会把文件移进垃圾桶,你至少还有撤回窗口。
这个思路适合放在仓库规则里,也适合放在个人 shell 环境里。不同系统里,你可能用的是 trash、trash-put、macOS 的同类工具,甚至是你自己的包装脚本。关键是行为语义:先进入垃圾桶,给自己留一个撤回窗口。
这一层的局限
问题在于,alias 和规则文件从来都算不上硬隔离。
alias 方面。Bash 官方手册明确写了:alias 默认只在交互式 shell 展开;非交互式 shell 除非显式打开 expand_aliases,否则不会替换。很多 Agent 调命令时,并不一定跑在你平时手敲命令的那个交互式环境里。也就是说,你在终端里 rm 被替换成了 trash,不代表模型通过脚本、子 shell 或工具调用发出的 rm 也会自动替换。
规则文件也一样。AGENTS.md、CLAUDE.md 确实有用,但它们是文本约束。模型可能遵守,也可能漏掉,还可能在上下文漂移、任务切换、工具调用链很长的时候绕开。给 rm 戴垃圾桶头盔,和给 AI 上儿童锁差不多。能挡掉一部分意外,但挡不住所有路线。
模型绕开的方式,至少有这几类
如果你只把防线押在"别用 rm",那模型真要删的时候,办法并不少。最常见的绕法至少有四类:
1. 直接调用绝对路径
/usr/bin/rm -rf some-dir如果你只做了 alias rm='trash',这种写法根本不会碰你的 alias。
2. 用移动代替删除
mv some-dir /dev/null这条命令本身未必在所有系统上都成立,但它代表的是同一类思路:绕过 rm 这个词本身,换一条文件系统路径做破坏性处理。你限制的是命令名,它走的是另一套操作语义。
3. 在脚本或解释器里删
import os
import shutil
from pathlib import Path
os.remove('notes.md')
Path('draft.txt').unlink()
shutil.rmtree('old-build')Python 官方文档里,os.remove() / os.unlink() 用于删文件,os.rmdir() 用于删空目录,shutil.rmtree() 则可以直接删掉整个目录树。只要模型能写脚本、能运行脚本,你限制 shell 命令名并不能挡住解释器层面的删除。
4. 重写后提交"空结果"
还有一类不那么显眼:它没有直接删文件,但会把文件内容大面积覆盖,或者把本来该保留的区块替换成空内容,再把结果当成"修复完成"交给你。对恢复来说,这和误删差别不大。
这里要记住的是:"使用 trash,不用 rm"只是第一层缓冲。
第二层:Git 解决的是"回到上一个可确认状态"
到了这里,Git 的角色就清楚了:它负责把你带回一个明确、可核对、可恢复的版本。
这一层的重点,是你有没有把 Git 用成工作流。
开工前建立分支
别让 AI 直接在你当前唯一的工作分支上乱跑。切一个专门分支,至少把这次实验的改动圈起来。
git switch -c ai/delete-defense-202605如果你更习惯旧命令,也可以:
git checkout -b ai/delete-defense-202605这样做的价值很直接:后续回退、比较、丢弃都会干净很多。
修改前检查工作区状态
每次把任务交给模型前,确认一眼仓库当前状态,别把旧改动和新改动混在一起。
git status --short
git diff如果一开始就堆着一批未提交文件,模型一旦误删或误改,事后很难分清哪些是旧问题,哪些是这次引入的。
关键节点一定要 commit
Git 能兜底的前提,是你手里有可以退回的提交点。最怕的是模型跑了半小时,期间没留任何 savepoint,结果一次性全丢。
一个实用做法是:
- 改动前留一个"起跑点";
- 跑完一个大步骤留一个"中间点";
- 准备交卷前留一个"候选结果点"。
命令很普通,但必须真做:
git add -A
git commit -m "wip: before ai edits"中途如果你验证过一个阶段性结果,也可以继续:
git add -A
git commit -m "wip: ai pass 1 verified"不要等到"全部做完再一起提交"。你等的这段时间,恰好是最可能把退路一起丢掉的时间。
AI 修改后的 diff 检查
模型跑完任务,别急着信它那句"已完成"。先把 diff 看完。
git diff
git diff --staged大删文件、大覆盖、奇怪重排、误动无关目录,这些东西在 diff 里通常比在自然语言回复里明显得多。
如果你看到它改了不该改的地方,别急着让它继续补救。这时最要紧的是保住现场,回退还是局部修,等 diff 看清再定。
真出事了,怎么用 Git 回来
恢复某个文件到当前提交版本
git restore path/to/file恢复整个工作区的未提交改动
git restore .从某个历史提交里捞回文件
git restore --source=<commit> path/to/file老一点的写法也可以:
git checkout <commit> -- path/to/file分支彻底跑偏了,直接回到前一个提交点
git log --oneline
git reset --hard <commit>这一步要谨慎,因为它会丢掉当前工作区的未保存改动。它适合你已经确认"当前这一坨都不要了"的时候。
.git 一起没了怎么办
这时候要冷静一点:本地 Git 已经帮不了你。
如果模型删的不只是业务文件,还把 .git 目录一起干掉,本地版本历史就没了。你能指望的只剩几种外部退路:
- 远程仓库还在,可以重新 clone;
- 还有别的本地副本、网盘快照、系统备份;
- 再不行才轮到文件恢复工具。
所以 Git 的正确定位是"版本化兜底"。它能救的,是已经进过版本控制、也有提交点可退的内容。
第三层:把规则文件当成活文档来维护
CLAUDE.md / AGENTS.md 要当活文档维护。
这句话比"写不写规则"本身更重要。很多人第一次被模型坑过后,会补一句规则;第二次、第三次又换别的坑,因为旧规则没人回头整理,新的坑也没人写进流程里。久而久之,规则文件要么太空,要么太乱。
更实用的做法是:每次翻车后,不只是让模型道歉,还要把这次纠正规则整理回文档。比如:
- 删除文件前必须先说明目标路径和原因。
- 涉及批量删除、重命名、移动目录时,先展示拟执行命令,再等待确认。
- 除非用户明确要求,不要执行 commit / push / merge。
- 运行脚本前,先解释脚本会触碰哪些路径。这类规则不能保证零事故,但会让后续同类错误变少。它的价值在于持续纠偏。
用户经验:别把它们当基准评测,但也别装没看见
下面这些内容都只按用户公开经验来写,不当成实验室 benchmark,也不当成模型厂商的正式结论。它们的价值在于提醒你:误删、误覆盖、奇怪行为,在不同模型上都可能出现。
Qwen
有用户在 LINUX DO 里直接写过:让 Qwen 3.5 Plus 去修 Git 错误,结果"直接删库了",还补了一句"codex 倒是靠谱很多,从来没有乱改我的文件"。这显然只是个人使用感受,但它至少说明一件事:你不能因为模型换了名字,就默认删文件风险自动消失。
DeepSeek
另一位用户记录的是 DeepSeek V4 Pro (max) 在一次 edit 操作里,把两个相同字段之间的几千行代码整段覆盖掉。第一次模型自己发现并修了一次,第二次直接交卷,用户后来的结论是:不敢再让它碰这个项目了。
还有一篇长文本格式保留的体验贴提到:在某些 docx 转 markdown 的场景里,DeepSeek 是唯一把多个换行保留下来的,速度也快;但同一位用户后来又补了一句,某些场景下 DeepSeek 的理解能力还是不够。一个模型可能在某个局部任务里表现不错,但不代表你就该给它高权限。
MiMo
MiMo 这边,公开帖子里既有"第一次尝试就拉了"的吐槽,也有更细一点的格式保留体验:有用户说 Qwen 和 MiMo 对 处理得不好,MiMo 速度快,但网页端没有"不思考"模式;也有人在分析项目时碰到离谱回答,清空上下文再问一次才恢复正常。
这些经验合在一起,只能说明一件事:只要模型拥有改文件权限,工作流和回退路径就得先建好,模型偏好反而该往后放。
一套更稳的"AI 改代码前"动作顺序
把这篇文章压成一份可执行清单,顺序可以这样:
1. 轻量防护
- 在
AGENTS.md/CLAUDE.md里写清楚删除规则。 - 能用
trash/trash-put/ 包装脚本的地方接上。 - 对批量删除、移动目录、执行脚本设置额外确认。
2. Git 起跑动作
git switch -c ai/safe-edit
git status --short
git add -A
git commit -m "wip: clean base before ai"3. 让模型每跑一段就停一次
- 大改前说计划;
- 改完就看 diff;
- 通过一个阶段就留一个 commit;
- 不要让它一路静默跑完全程。
4. 问题发生后的现场保全
git diff
git status
git restore path/to/file先把现场收住,再决定要不要继续让它修。
5. 事后把规则补回文档
- 这次是删文件,就补删除规则;
- 这次是误提交,就补 Git 规则;
- 这次是脚本误伤,就补脚本执行范围。
这样做几轮之后,文档才会真的长成团队的防翻车手册。
把顺序固定下来
用 trash 和确认规则减少直接误删,再用 Git 留分支、提交点和 diff,后面把翻车经验补回 AGENTS.md 或 CLAUDE.md。如果项目真的重要,再往外补远程仓库、系统快照和额外备份。
顺序固定下来,AI 就算走偏,你手里也还有回头路。