先打个比方:Git的commit就像给当前代码拍了张"快照",标注了"截止到这里的修改"。撤销commit不是删代码,而是根据需求"删快照""改快照说明"或者"抵消快照效果",核心看两个关键点:快照有没有分享给别人(推送到远程仓库) 和是不是刚拍的快照(最近一次提交)。
一、最常用:刚提交完,还没推给别人(本地快照)
这种情况最自由,怎么改都不影响同事,分三种常见需求。
1. 提交信息写错了(比如把"修复登录bug"写成"修复登路bug")
不用删快照,直接改"快照说明"就行,执行下面命令:
git commit --amend
执行后会弹出一个编辑框,把错的信息改对,按Ctrl+S保存,再按Ctrl+X退出,就搞定了。如果改的时候发现漏加了文件,先执行git add 漏加的文件路径,再用这个命令,会把文件一起塞进这个快照里。
2. 想删快照,但代码修改要保留(比如手滑提前提交了)
比如你刚commit,但突然想到还有一段代码没改完,想把快照删掉,继续改代码,之后再重新提交。分两种细致需求:
-
情况A:改好的代码想留在"待提交区" (就像东西打包好了,暂时不发快递) 执行命令:
git reset --soft HEAD~1效果:快照没了,但之前改的代码都在,执行git status会看到文件标着"已暂存",之后改完直接commit就行。 -
情况B:改好的代码想重新"挑选" (比如打包时不小心把没用的文件也装进去了) 执行命令(直接输,不用加额外参数):
git reset HEAD~1效果:快照没了,改的代码也在,但文件回到了"未暂存"状态,需要重新用git add挑选要提交的文件。
小贴士:HEAD~1就是"最近1次提交"的意思,想删最近2次就写HEAD~2,以此类推。
3. 彻底删快照+删修改(提交错了,代码全不要了)
比如你提交了一段烂代码,确定这些修改没用,想回到上一次提交的干净状态,执行命令:
git reset --hard HEAD~1
警告:这个命令会把你本次提交的代码修改彻底删掉,删了就找不回了(除非用后面的"后悔药"方法),一定要确认代码没用再用!
二、要小心:提交已经推给别人了(远程快照)
这种情况快照已经同步到团队共享的仓库了,不能直接删,否则同事拉代码时会出问题,核心思路是"拍一张新快照抵消旧的"。
1. 安全方法:反向提交(推荐)
就像写作文写错了,不划掉原文,而是在后面写"上文作废",所有人都能看到修改记录,步骤如下:
-
先找到要撤销的快照ID:执行
git log --oneline,会列出所有快照,比如看到a1b2c3d 新增了搜索功能,前面的a1b2c3d就是这个快照的ID(每个人的都不一样)。 -
执行反向提交命令:把ID换成你找到的那个,比如
git revert a1b2c3d。 -
弹出编辑框,写清楚"撤销新增搜索功能的提交",保存退出。
-
把新快照推给远程:执行
git push,这样所有人拉代码后,旧的错误修改就被抵消了。
如果要撤销的是"合并分支的提交",需要加个参数:git revert 合并快照ID -m 1,这里的"1"不用改,意思是保留主分支的内容。
2. 冒险方法:强制覆盖(仅限个人仓库)
如果这个仓库只有你一个人用,不怕影响别人,可以先在本地删快照,再强制推给远程,命令如下:
git reset --hard HEAD~1 # 本地删最近一次快照 git push -f origin 你的分支名 # 强制推送到远程,比如git push -f origin main
严重警告:团队协作仓库绝对不能用!会把远程的历史记录直接覆盖,同事的代码可能会丢,出问题要背锅的!
三、后悔药:不小心删错快照了(找回来)
如果误执行了git reset --hard,把有用的快照删了,别慌,Git有"操作日志",能找回30天内的所有快照,步骤如下:
-
执行
git reflog,会列出你所有操作记录,比如看到89abcde HEAD@{2}: commit: 修复了支付bug,这个89abcde就是你删错的快照ID。 -
执行
git reset --hard 89abcde,就能回到这个快照的状态,代码全回来了。
四、一张表总结:不用记命令,照着查
| 你的场景 | 直接用这个命令 | 关键提醒 |
|---|---|---|
| 提交信息写错,没推远程 | git commit --amend | 改完保存退出就行 |
| 删快照,留代码(没推远程) | git reset --soft HEAD~1 | 代码在"待提交区" |
| 删快照,代码重新选(没推远程) | git reset HEAD~1 | 代码要重新git add |
| 提交错了,代码全不要(没推远程) | git reset --hard HEAD~1 | 删了找不回,谨慎! |
| 提交已推远程,要撤销 | git revert 快照ID + git push | 安全,团队必备 |
| 删错快照,要恢复 | git reflog → 找ID → git reset --hard ID | 30天内的都能找 |
最后记个核心原则:没推远程的随便改,推了远程的用revert,这样既能解决问题,又不会给团队添乱~