Git撤回已经提交(甚至已push)的代码,但把改动留在本地的解决
这个坑,基本上每个用Git的开发者都会踩一次: 刚执行完commit,顺手就push上去了。 过了两分钟才反应过来:这次提交不应该上去。 但问题是—— 代码本身还要留着继续改,不能直接删掉。 这篇文章只解决一件事: 如何把提交从历史中抹掉,同时让代码留在本地 公共分支上请慎用这个方法,独立开发时可以
这个坑,基本上每个用Git的开发者都会踩一次:

刚执行完commit,顺手就push上去了。
过了两分钟才反应过来:这次提交不应该上去。
但问题是——
代码本身还要留着继续改,不能直接删掉。
这篇文章只解决一件事:
如何把提交从历史中抹掉,同时让代码留在本地
公共分支上请慎用这个方法,独立开发时可以放心使用。
先说人话版结论
如果你只是遇到这种情况:
- 刚push完
- 想撤回最近一次提交
- 代码还想保留
记住下面两步就够了:
git reset HEAD~1 git push --force-with-lease origin main
执行完成后:
- 远端仓库看不到这次提交了
- 本地
git log也查不到 - 代码还在,只是变成了未提交的状态
大多数情况下,到这一步就解决问题了。
这两条命令到底做了什么
第一条
git reset HEAD~1
意思是让当前分支指针倒退一个提交位置。
但注意:它不会删除你的代码,只是把:
- commit 里的内容
- 变回工作区的改动状态
所以你会看到文件还在,只是状态变成了“未提交”。
第二条
git push --force-with-lease origin main
用你当前本地的 main 分支,覆盖远端 main 的内容。
也就是把刚才“回退后的状态”同步到远程仓库。
如果想更精确控制,可以指定commit id
有些人不太喜欢“直接把当前分支推上去”的方式,更希望明确指定要回到哪个提交。这时可以用commit id来实现。
第一步:查commit id
最简单的方法:
git log --oneline
比如看到这样:
070505c github page ← 这是你想撤回的提交 ff775f6 first commit ← 这是你要回退到的位置
记住:你需要的是前一个“正确提交”的id。
如果想看更清晰的视图:
git log --oneline --graph --decorate -5
第二步:本地回退到这个id
git reset --mixed ff775f6
效果是:提交记录回退了,代码还在,但不在暂存区。
如果你希望改动仍保留在暂存区:
git reset --soft ff775f6
第三步:强制远端也回退
git push --force-with-lease origin ff775f6:main
这句的意思很直白:让远端 main 分支指向 ff775f6 这个提交。
执行之后的效果
- GitHub 上看不到那次错误提交
- 本地历史里也没有
- 代码还在本地,可以继续修改
这正是很多人需要的操作:撤回提交但保留代码。
什么时候需要“三段式写法”?
你可能见过这种写法:
git reset --hardgit push --force-with-lease origin :main git cherry-pick --no-commit <某个提交>
这套操作属于补救方案,不是常规操作。
它通常适用于:已经用 reset --hard 清掉了代码,或者想只恢复某一次提交的内容。
在正常情况(刚提交就反悔)下,用不到这种较重的操作。
为什么不推荐用git revert
很多教程会推荐使用:
git revert
但它做的是新增一个“反向提交”,换句话说:原来的错误提交还在,只是多了一次撤销它的提交记录。
如果你的目标是让这次提交彻底从历史中消失,那就不要用 revert。
这个操作有风险吗?
有,而且需要说清楚。
因为使用了:
git push --force-with-lease
这属于改写历史的操作。
风险1:可能覆盖别人的提交
如果在push之前,别人已经往 main 分支提交了新代码,那么这一push可能会把对方的提交顶掉。
风险2:别人本地会乱掉
改了远端历史之后,其他人本地的历史还是旧的,pull或push时可能产生冲突,甚至把你删掉的提交再带回来。
如何尽量安全操作
1. 尽量避免在多人共用的分支上乱用
特别是 main 分支正在被多人提交时。
2. 务必使用这个
git push --force-with-lease
而不是:
git push --force
前者至少会检查远端有没有被别人改过。
3. 操作前先看一眼远端状态
git fetch origin git log --oneline --graph --decorate --all -10
4. 如果提交已经被别人拉取过,就别改历史了
这种情况更建议用:
git revert
最后给一个记忆版本
如果你只是“刚push,想撤回,但代码要留着”,记住这套命令就够了:
git reset HEAD~1 git push --force-with-lease origin main
如果你希望完全可控(明确回到某个点):
git log --oneline git reset --mixedgit push --force-with-lease origin :main
总结一下
这件事本质其实就一句话:删的是提交记录,不是代码内容。
理解这个核心操作,Git基本就算入门了。

































