【Git基础】03——Git 撤销与回退:改错了怎么办

​ 写代码总会手滑。改了半天发现方向错了,或者 commit 信息写错了,甚至把不该提交的东西提交上去了,这些都是日常。Git 的撤销体系看起来命令很多,但核心其实只有一句话:先判断改动在哪一层,再选择对应的撤销工具。只要这点清楚,Git 的"后悔药"其实非常好用。

引言

​ 先建立一张地图,Git 追踪改动分三层:

  • 工作区(Working Directory):你正在编辑的文件

  • 暂存区(Staging Area) :执行 git add 之后

  • 提交历史(Commit History) :执行 git commit 之后

撤销操作的方向,本质就是沿着这条链 向后退

​ 三层结构图:工作区、暂存区、提交历史依次排列,撤销操作是沿着这条链往回走的过程。

一、场景一:还没 add,直接丢弃工作区改动

​ 你改了一个文件,还没 add,现在想把它恢复到上次提交的状态:

bash 复制代码
git restore README.md

​ 这条命令会丢弃工作区的改动 ,文件直接回到最近一次 commit 的版本。注意,这个操作是不可逆的,因为工作区的修改没有进入Git历史。

​ 旧版 Git 用的是 git checkout -- README.md,效果一样,只是语义不够清晰。现在推荐统一用 git restore

二、场景二:已经add,但还没 commit

git add 之后反悔了,想把文件从暂存区拿回来:

bash 复制代码
git restore --staged README.md

​ 加了 --staged 就是针对暂存区操作。执行后,文件回到"已修改但未暂存"的状态,工作区的改动还在,只是不再准备提交了。

​ 如果想一步到位,既撤销暂存,又丢弃工作区修改,推荐分两步:

bash 复制代码
git restore --staged README.md
git restore README.md

意图清晰比命令短更重要

三、场景三:已 commit,怎么办

这里是 Git 新手最容易混乱的地方

​ 这里要区分两种情况:这个 commit 有没有推送到远程

3.1 没推送:可以用 git reset

git reset 会移动HEAD指针,改写提交历史

​ 有三种模式:

模式 改动去向
--soft 回到暂存区
默认(mixed) 回到工作区
--hard 直接丢弃
(1) commit -> 暂存区
bash 复制代码
git reset --soft HEAD~1
(2) commit -> 工作区
bash 复制代码
git reset HEAD~1
(3) commit 直接删除
bash 复制代码
git reset --hard HEAD~1

​ 三个模式的区别在于改动去哪里:--soft 退回暂存区,默认(--mixed)退回工作区,--hard 直接扔掉。--hard 用之前要想清楚,它是真正的删除按钮,改动没有备份,找回来非常麻烦。

3.2 已推送:必须用 git revert

​ 一旦 commit 推送到了远程,绝对不要用 git reset。原因很简单:远程已经有这个commit的记录,你本地改写历史之后,推送会被拒绝;就算强推成功,协作的同事拉代码时会遭遇历史冲突,现场一片混乱。

​ 正确做法是 git revert

bash 复制代码
git revert HEAD

​ 它不会删除commit,而是会生成一个新的 commit,内容是把目标 commit 的改动反向应用一遍。历史链条不动,安全,可追溯。

复制代码
提交历史:A → B → C(需要撤销 C)
revert 后:A → B → C → C'(C' 是 C 的逆操作)

reset 直接把 HEAD 往回挪,C 从历史中"消失",本地没问题,但如果这个 commit 已经推送到远程,别人的历史里还有 C,强推会导致冲突。而revert 则是在 C 后面追加一个反向 commit C',历史只增不删,对协作者完全透明,这就是为什么已推送的 commit 必须用 revert。

​ 代价是历史会多一条记录,但这正是团队协作里应有的透明度。

四、git stash:保存现场,去干别的

​ 有一种场景 reset 和 revert 都处理不了:你改到一半,突然需要切分支处理紧急 bug。改动还没到能提交的程度,但直接切分支又可能出现冲突或者把改动带过去。

​ 这时候可以用 git stash

bash 复制代码
git stash

​ 它会把当前工作区和暂存区的改动打包藏起来,让你的工作目录回到干净状态。处理完紧急任务,切回原来的分支,再把现场恢复出来:

bash 复制代码
git stash pop

pop 会把最近一次 stash 的内容恢复,并从 stash 列表里移除。如果想保留记录,用 git stash apply 代替。

​ 有时候同时有几个 stash,可以用 git stash list 查看,git stash pop stash@{1} 指定恢复哪一个。

五、决策表:碰到问题查这里

当前状态 目标 命令
工作区有改动,未 add 丢弃改动 git restore <file>
已 add,未 commit 撤销暂存 git restore --staged <file>
已 commit,未推送 撤销 commit git reset HEAD~1
已 commit,已推送 撤销 commit git revert <commit>
改到一半要切分支 临时保存现场 git stash / git stash pop

​ 撤销体系的核心逻辑就是一句话:改动走到哪一层,用对应层的工具往回退;已经共享出去的历史,只能用新 commit 来修正,不能改写

相关推荐
恼书:-(空寄7 小时前
ES性能调优实战指南
elasticsearch
小黑要努力8 小时前
智能音箱遇到的问题(一)
linux·运维·git
RePeaT8 小时前
【git】指令场景实战:单分支与多分支协作流程
git
折哥的程序人生 · 物流技术专研9 小时前
效率翻倍:出版社多库区复合型 ABC 仓储拣选体系全解(含直发/越库/箱式立库/托盘立库)
大数据
Elastic 中国社区官方博客9 小时前
Elasticsearch:智能搜索 - AI builder 及 skills
大数据·人工智能·elasticsearch·搜索引擎·ai·信息可视化·全文检索
跨境摸鱼9 小时前
低价模型承压阶段跨境品牌如何把重心转向复购与客单
大数据·人工智能·跨境电商·亚马逊·跨境
前端Hardy10 小时前
杀疯了!Git 2.54 正式发布,3个封神新特性,效率直接翻倍!
git
果汁华10 小时前
LangGraph:构建状态化 AI 代理的革命性编排框架
大数据·人工智能
面向Google编程10 小时前
从零学习Kafka:生产者分区机制
大数据·kafka
盘古信息IMS11 小时前
全域场景重构,激活智造新未来!盘古信息机加行业数智化解决方案深度解析
大数据·人工智能