今天下午对着 Claude 搓了一下午功能,跟着 Vibe Coding 的节奏一路狂飙,想到啥就让 AI 写啥,能跑就 commit,半天攒了好几个提交。 回头想撤销掉最后一次瞎试的提交,顺手敲了个
git reset --hard HEAD^,回车的瞬间我就知道坏了 ------ 刚写的半屏代码直接没了,冷汗唰就下来了。
先从下午那次惊魂说起
当时的提交记录是这样的,三个提交,最新的一次是 append GPL,就是我想撤掉的那次。

说实话我之前对 reset 一直一知半解,只知道能回退版本,后面加啥参数全靠瞎蒙。那天脑子一抽选了 --hard,执行完再看文件,新增的内容全没了,工作区干干净净。 我当时人都傻了,一下午的成果不会就这么没了吧? 慌慌张张翻终端历史记录,幸好刚才扫了一眼 commit id,抱着试试看的心态又敲了一遍 git reset --hard 0564f0d,回车之后代码回来了,心脏才落回肚子里。
经这么一吓,我也没心思写功能了,干脆坐下来把 reset 的几个模式彻底掰扯清楚,省得下次再踩同样的坑。
把 reset 的几个模式掰开揉碎说
先说好理解的,HEAD 是啥? 你就把它当成你当前的游戏存档指针,它永远指着你现在正在用的这个版本。HEAD^ 就是上一个存档,HEAD^^ 就是上上个,往前数得多了也可以写 HEAD~3,意思是往前数第三个版本。 reset 本质上就是移动这个指针,把它挪到你想去的那个版本上。几个模式的核心区别,就在于挪动指针之后,你工作区、暂存区里的代码要怎么处理。
--hard:硬核回档,寸草不生
先说我踩坑的这个 --hard。 顾名思义,它很硬,也很粗暴。执行之后,不仅提交记录回退到目标版本,连你的工作区、暂存区的所有修改,都会被直接抹掉,整个项目变回目标版本当时的样子,干净得像你从来没写过后面的代码一样。
bash
# 回退到上一个版本,所有未提交、已暂存的修改全部删除
git reset --hard HEAD^
适合什么场景呢?就是你彻底写崩了,后面的代码全是垃圾,想全盘推倒重来,回到某个干净的节点重新开始。
没事别随便敲 --hard,尤其是你还有没提交的本地修改的时候,删了真的很难找回来。
--soft:撤销提交,代码留下
缓过来之后我试了试 --soft,打开了新世界的大门。 执行 git reset --soft HEAD^ 之后,提交记录确实回退了,但我改的代码一点没少,而且自动放在了暂存区里,就差最后一步 commit 了。
说白了,--soft 就是 "我后悔刚才点提交了,但代码我还要"。相当于把刚打好的提交包拆开,内容原封不动还给你,你改改提交信息、或者再加点东西,还能重新提交。 我平时最常用的就是这个,比如刚 commit 完发现漏了个文件、或者提交信息写错了,用 --soft 撤回来,改完再重新提交,非常方便。
从暂存区到工作区,一层层撤销
既然说到这了,干脆把整条撤销链路都说完。 现在代码在暂存区,我不想提交了,想放回工作区再改改,怎么办? 用 git restore --staged 文件名。
执行完你再看状态,文件就从 "待提交" 变成了 "已修改但未暂存",相当于撤销了 git add 这一步。 那如果工作区的修改我也不想要了,想彻底恢复成上次提交的样子呢? 用 git checkout -- 文件名。
这一下就彻底清净了,文件回到了上次提交的状态,提交记录也一点没动。相当于 "写得太烂了,全部删掉重写"。 你看,整个撤销过程是分层的:提交记录 -> 暂存区 -> 工作区,每一层都有对应的操作。以前我死记硬背总记混,现在顺着这条线捋一遍,再也没乱过。
为什么我会踩这个坑?
平复下来之后我就在想,我用 Git 也不是一天两天了,怎么还会犯这种低级错误? 说穿了,就是最近搞 Vibe Coding 太上头,节奏全乱了。 以前自己写代码,改一个功能要琢磨半天,commit 也会认真写信息,一天也就两三个提交。现在不一样了,想到一个点子就让 AI 写,跑通了就随手 commit,一天能攒十几个乱七八糟的提交。 需求边想边改,代码边写边删,Git 完全成了个 "保存一下" 的工具,根本没什么规范可言。直到要回退版本的时候才傻眼,不仅提交信息看不懂,连命令都记混了。
AI 写代码越快,越需要先搭架子
这段时间很多人聊 Vibe Coding,说 AI 写代码有多快,程序员要失业了。 我自己用下来的感受是,写代码的速度确实快了很多,但代码烂掉的速度也快了很多。如果上来就直接让 AI 开写,想到哪写到哪,不出三天项目就变成屎山。你改一个地方崩三个地方,最后越改越差,整个项目直接崩盘。 问题根本不在 AI 够不够强,而在于很多人把 Vibe Coding 理解成了 "把活丢给 AI 就完事了"。实际上恰恰相反,AI 越强,越需要人来搭架子、定规矩,也就是现在常说的 Harness Engineering------ 驾驭 AI 的工程能力。 这段时间我也在摸索这套流程,总结下来一句话:写代码之前的功夫,比写代码本身还重要。
第一阶段:先定图纸,再动工
写代码之前,先别着急开项目、装依赖。 第一步是聊需求。就像跟朋友唠嗑一样,把你想解决的痛点、目标用户是谁、核心功能有哪些,全跟 AI 说清楚。不用追求严谨,想到啥说啥,先把大方向聊透。 聊完不能就这么算了,得让 AI 整理成一份正经的 PRD 文档。最关键的是,每个功能都要写清楚验收标准 ------ 做到什么程度才算做完。 比如 "登录功能",不能只写 "做个登录",得写清楚登录失败提示什么、成功了跳转到哪、要不要记住登录状态。没有边界的需求,AI 能给你越写越偏,最后收都收不住。 功能定完了,还得定视觉。找两三个参考网站,或者让 AI 出几套风格方案,定下来整体走什么风格、页面大概怎么布局。别等写功能的时候一边写逻辑一边改 UI,来回返工最浪费时间。
第二阶段:地基打牢,少返工
图纸画完了,接下来是打地基。 先想清楚项目的边界:这是自己本地跑的玩具,还是要上线给别人用的?预计用户量多少?要不要做用户系统、接支付?性能、安全、成本有没有上限? 这些非功能需求最容易被忽略,但往往是后期返工的重灾区。你一开始没说要支持多用户,AI 就会写死成单用户逻辑,等后面想加的时候,整个数据层都得推翻重写。 然后锁定技术栈。别追新,就用自己最熟的,出了问题你能兜得住的。对我来说就是 React + TS + Tailwind,AI 写起来稳定,我排查问题也快。 技术栈定完,让 AI 出一份轻量的架构草案:目录怎么分层、核心模块有哪些、数据模型长啥样。不用太复杂,大概有个谱就行,总比写到哪算哪强。
第三阶段:把规矩写进文件里
最后一步,也是最关键的一步:把前面定好的所有东西,全部固化成项目根目录下的文本文件。 PRD.md 放需求,DESIGN.md 放设计规范,ARCH.md 放架构设计,再整个 PROJECT.md 记录当前进度。 别小看这几个 md 文件,它们就是 AI 的 "全局宪法"。后面每次跟 AI 对话,都让它先读一遍这些文档,保证它写的东西不跑偏。Vibe Coding 不是跟着感觉瞎写,而是在既定框架里快速迭代。 除此之外,代码规范、接口规范、Git 提交规范,全部提前定好。就像今天这个 Git 的坑,如果每次提交都规规矩矩写清楚信息,回退的时候也不至于慌慌张张敲错命令。
最后说两句
今天本来只是想搞懂 git reset 的区别,结果顺着想了这么多。 说白了,AI 只是个效率放大器。你规范做得好,它能帮你十倍速出活;你本身就乱糟糟的,它能把烂代码放大十倍。 最后再念叨两句印象最深的: 第一,--hard 是全删,没事别瞎用;只想撤销提交保留代码,用 --soft。 第二,别上来就哐哐写代码,先定规矩再动手。AI 越快,越要慢下来做规划。 搞懂了的话可以回去试试手,踩了别的坑也欢迎回来聊聊,我也想看看大家用 AI 写代码都有啥奇奇怪怪的翻车经历。