Git提交错了,别慌!还有后悔药

大家好,我是晓凡。

写代码就像炒菜,锅铲一抖盐放多了还能加水,Git 提交错了也能"回锅"。

但回锅方法不对,可能把整锅菜都糊掉。

今天咱们就掰开揉碎聊聊:到底有哪些"提交错了"的场景?

每种场景到底该怎么优雅地撤回?全部给你配好命令、画好流程,照着抄就行。

一、先分清"锅"在哪儿

首先我们得分清"锅"在哪儿,本地还是远程?

Git 把仓库分成三大块:

  1. 工作区(Working Directory):你电脑上看得见的文件夹。
  2. 暂存区(Index / Stage):git add 之后放东西的地方。
  3. 本地仓库(Local Repo):git commit 之后放东西的地方。
  4. 远程仓库(Remote Repo):GitHub、GitLab、gitee 等远端服务器。

搞错一次提交,先问自己一句:

"锅"现在停留在哪一层?

  • 只在工作区?
  • 只在暂存区?
  • 已经 commit 但还没 push?
  • 已经 push?
  • 甚至 push 完别人已经拉下来继续开发了?

不同位置,撤回姿势完全不同。下面分场景,逐个拆招。

二、场景 1

add 错了,还没 commit

症状

git add 了不该 add 的文件,比如把 node_modules 也扔进去了,但还没 commit。

解决 把东西从暂存区踢回工作区即可:

bash 复制代码
# 全部撤回
git reset HEAD .

# 只撤回某个文件
git reset HEAD package-lock.json

三、场景 2

commit 写错信息,或忘了加文件

A. 只想改 commit message

bash 复制代码
git commit --amend -m "新的提交说明"

B. 漏了文件

bash 复制代码
git add forgotten.java
git commit --amend --no-edit   # 不改动 message

注意:amend 会生成新的 commit-id,如果已经 push 过,就属于"改写历史",需要强制推送(见后文)。

四、场景 3

commit 错了,但还没 push

  1. 最后一次 commit 想直接作废
bash 复制代码
# 撤回 commit,改动保留在工作区
git reset --soft HEAD~1
# 或者
git reset --mixed HEAD~1   # 默认模式,改动回到工作区
  1. 连改动都不要,彻底删除
bash 复制代码
git reset --hard HEAD~1
  1. 倒数第 N 次提交都错了
bash 复制代码
# 回退 3 个提交
git reset --hard HEAD~3

流程图

注意:--hard 会丢改动,先确认没重要代码。

五、场景 4

已经 push,但没人基于它开发

思路:先本地回退,再强制推送。

步骤

1)本地回退

bash 复制代码
git reset --hard <回退到的commit-id>

2)强制覆盖远端

bash 复制代码
git push --force-with-lease origin main

为什么用 --force-with-lease 而不是 --force

前者会检查远端有没有人比你先 push,避免把同事的 commit 冲掉,更安全。

六、场景 5

已经 push,且同事已拉取并继续开发

此时"改写历史"会让同事陷入混乱,禁止 reset + force push。

正确姿势:用"反转提交"(revert)。

示例

bash 复制代码
# 生成一个新的 commit,把错误提交的内容"反着做一遍"
git revert <错误commit-id>
git push origin main

如果一次 revert 不够,可以连续 revert:

bash 复制代码
git revert OLDEST_COMMIT^..NEWEST_COMMIT

流程图

main: A-B-C-D-E(错误)

revert 后:A-B-C-D-E-F(撤销E)

优点:历史干净、无冲突风险;缺点:会多一个 commit,强迫症可能不爽。

七、场景 6

merge 错了,还没 push

A. 刚 merge,发现合错分支

bash 复制代码
git reset --hard HEAD~1   # 直接回到 merge 前

B. merge 了很久,已产生大量后续 commit

思路:用 git revert -m 反转 merge commit。

bash 复制代码
git revert -m 1 <merge-commit-id>

-m 1 表示保留 merge 的第一个父分支(通常是 main)。

八、场景 7

rebase 错了,想反悔

rebase 过程中冲突太多,想直接放弃:

bash 复制代码
git rebase --abort

已经 rebase 完但后悔了:

bash 复制代码
# 查看 reflog 找到 rebase 前的 HEAD
git reflog
git reset --hard HEAD@{2}

九、场景 8

cherry-pick 错了

bash 复制代码
# 撤销刚 cherry-pick 的 commit
git cherry-pick --abort

如果已经 commit,可用 revert 回滚单个 cherry-pick 的 commit。

十、万能后悔药:reflog

Git 在本地会记录每一次 HEAD 的移动。

不管 reset、rebase、merge 玩得多花,只要没 gc,都能找到"案发前"的位置。

bash 复制代码
git reflog
# 找到想回去的 id
git reset --hard 9f3e2a1

十一、一张总览流程图

十二、踩坑小贴士

  1. 任何 reset --hard 前,先 stash 或备份分支:git branch backup
  2. 多人协作时,默认"不能强推",可在服务端开启保护分支。
  3. 强制推送后,通知团队所有人执行 git pull --rebase 同步。
  4. 重要操作前,用 git log --oneline --graph 看一眼历史,心中有数。
  5. 养成 commit 粒度细、消息清晰的习惯,能减少 80% 回滚需求。

十三、记住这一句话

add 错了 reset

commit 错了 amend/reset

push 错了先问队友,没人用就 force,有人用就 revert。

实在搞不清,reflog 带你穿越回过去。

祝你再也不用"删库跑路",回滚也能优雅如风。

我是晓凡,再小的帆也能远航

本期内容就到这儿

我们下期再见ヾ(•ω•`)o (●'◡'●)

相关推荐
最贪吃的虎11 小时前
GitHub推送又超时了?试试SSH
运维·ssh·github
smachao11 小时前
Redis Desktop Manager(Redis可视化工具)安装及使用详细教程
redis·git·bootstrap
szcsun512 小时前
git的常用命令
git
jian1105813 小时前
android studio 解决git用户名和用户邮箱不一致的问题
git
jian1105813 小时前
Mac git配置账号和邮箱,可以修改
git·macos
笨笨饿15 小时前
博客目录框架
c语言·开发语言·arm开发·git·嵌入式硬件·神经网络·编辑器
四千岁17 小时前
Obsidian + jsDelivr + PicGo = 免费无限图床:一键上传,全平台粘贴即发
前端·程序员·github
wusfe17 小时前
适配 Anthropic 兼容 AI 提供商的环境配置快速切换工具
github
Rabbit_QL17 小时前
【CI/CD】02_一次 git push 后发生了什么?CI 是怎么工作的
git·ci/cd