← 返回首页
Git 代码回退 / 回滚命令速查

Git 代码回退 / 回滚命令速查

发布于 2026年8月16日 23:094 分钟阅读👁 10

场景:代码改坏了、想撤销某次提交、想放弃未提交的改动。 本文档结合本项目实际案例整理,按「危险程度」从低到高排列。


一、先搞清楚三个概念

术语含义对应状态工作区你正在编辑的文件git statusM 开头的就是暂存区(index)git add 之后git status 里绿色的是**历史(HEAD)**已 git commit 的记录git log 能看到

核心心法:回退前先想清楚——你要撤销的是"未提交的改动"还是"已经提交/推送的提交"?这两类处理方法完全不同。


二、撤销「未提交」的改动(最常用、最安全)

2.1 丢弃工作区的修改(还没 add)

# 丢弃单个文件
git checkout -- app/components/Markdown.tsx
 
# 丢弃所有文件的修改
git checkout -- .
# 或
git restore .
 

2.2 丢弃已 add 但未 commit 的改动

# 从暂存区移回工作区(文件内容不变)
git restore --staged app/components/Markdown.tsx
 
# 同时丢弃暂存 + 工作区的修改
git checkout HEAD -- app/components/Markdown.tsx
 

⚠️ 以上命令永久丢弃未提交的改动,无法找回。如果改动很重要,先 git stash 暂存起来:

git stash           # 暂存所有未提交改动(可以反悔)
git stash pop       # 恢复刚才暂存的改动
git stash list      # 查看暂存列表
 

三、撤销「已提交」但「未推送」的提交(本地 commit)

3.1 reset 软回退(推荐,保留改动在工作区)

# 撤销最近 1 次提交,改动回到暂存区(文件内容还在,可以重新提交)
git reset --soft HEAD~1
 
# 撤销最近 1 次提交,改动回到工作区(未 add 状态)
git reset HEAD~1        # 等同 --mixed
 

3.2 reset 硬回退(彻底删除提交和改动)

# 彻底回退到上一版本,丢弃这次提交的所有改动(慎用!)
git reset --hard HEAD~1
 

💡 HEAD~1 = 上一个提交,HEAD~3 = 上三个,也可以直接用提交 hash:git reset --hard abc1234


四、撤销「已推送」的提交(本次项目实际案例)⭐

场景:CSDN 风格的 Markdown 排版提交 150085e 已经 push 到 GitHub / Vercel 已部署,后来决定不要了,要回退到上一版本。

4.1 推荐:git revert(生成反向提交,不改写历史)

# 撤销某个已推送的提交(自动生成一个"反向"的新提交)
git revert 150085e
 
# 推送回远程,Vercel 自动重新部署
git push my-blog main
 

特点

  • ✅ 历史完整保留(面试讲起来是"可审计的")
  • ✅ 普通 push 即可,不需要 force
  • ✅ 其他人/CI 不会因为历史改写而冲突
  • ✅ 可以安全地针对任意一个已推送提交(不限于最后一个)

本次实际执行:

git revert --no-edit 150085e
# 生成 [main 798701d] Revert "style: Markdown 排版改为 CSDN 风格..."
git push my-blog main   # 150085e..798701d main -> main
 

4.2 备选:reset + force push(改写历史,慎用)

# 回退到上一版本(本地)
git reset --hard HEAD~1
 
# 强制推送覆盖远程(危险!会改写远程历史)
git push --force my-blog main
# 或更安全的形式(防止覆盖别人新推的提交):
git push --force-with-lease my-blog main
 

特点

  • ⚠️ 改写了远程历史,禁止用于协作分支(多人共用 main 时会导致别人冲突)
  • ⚠️ force push 后,Vercel 可能因为"提交未验证"等问题出幺蛾子
  • ✅ 适合:单人项目、明确要抹掉某段历史的场景

💡 为什么本项目用 revert 而不是 reset --hard + force push? 因为历史已经被推送到远程且 Vercel 已部署——改写历史会破坏 Vercel 的部署追踪、GitHub 的提交记录,而且完全没必要。revert 达到同样的"代码回到上一版"效果,代价是历史里多一条 Revert 提交,干净且安全。


五、回退到"某次提交"的多个常用命令

git log --oneline -10          # 查看最近提交(拿 hash)
git show 150085e --stat        # 看某次提交改了什么文件
git revert <hash>              # 撤销任意一次提交(推荐)
git reset --hard <hash>        # 硬回退到某次提交(丢后面的所有提交,慎用)
git diff HEAD~1 --stat         # 看上一个提交和现在的差异
 

六、本次案例完整复盘(项目实际场景)

背景:写文章页 Markdown 排版时,先做了"专业排版重写"(提交 0e5f2b3),又按 CSDN 风格重写(提交 150085e)。用户觉得 CSDN 版本不好看,要求回退到上一版。

实际执行过程

# 1. 先看本地状态——发现 CSDN 提交其实已经 push 到远程了
git fetch my-blog && git status -sb
# 输出: ## main...my-blog/main   (本地与远程同步,说明远程已是 CSDN 版)
 
# 2. 确认要回退的提交内容
git show 150085e --stat
# 输出: 3 files changed(Markdown.tsx / CodeBlockCopy.tsx / globals.css)
 
# 3. 生成反向提交(revert)
git revert --no-edit 150085e
# 输出: [main 798701d] Revert "style: Markdown 排版改为 CSDN 风格..."
 
# 4. 推送,Vercel 自动部署回退版
git push my-blog main
# 输出: 150085e..798701d  main -> main
 

结果:线上回到 CSDN 之前的排版,历史完整保留,无 force push。


七、命令速查表

需求命令丢弃未提交的单个文件改动git checkout -- <file>丢弃所有未提交改动git checkout -- .暂存未提交改动(可反悔)git stash / git stash pop撤销未推送的提交(保留改动)git reset --soft HEAD~1彻底撤销未推送的提交git reset --hard HEAD~1撤销已推送的提交(推荐)git revert <hash> + push强制覆盖远程(慎用)git push --force-with-lease查看提交历史git log --oneline看某次提交改了什么git show <hash> --stat


八、避坑要点

  1. git status / git log 再动手——确认改动是否已提交/推送,方法完全不同
  2. git checkout -- git reset --hard 不可逆——重要改动先 git stash
  3. 多人协作的项目禁用 force push——用 git revert
  4. revert 是"再加一条提交",不是删历史——所以 push 不会失败,CI/Vercel 都正常
  5. 远程已部署过的东西想回退,永远优先 revert——reset+force 会让 Vercel 部署追踪混乱

评论 (0)

还没有评论,来写第一条吧~

写评论