Git 撤销已提交远程仓库的推送

📝 前言

在使用 Git 时,常常会因为“手滑”把还没准备好的内容直接推送到远程仓库,或者推送完才发现问题 😅 。

虽然可以再补一个修正提交来“打补丁”,但这会在提交历史里留下尴尬的“黑历史”。

为了保持历史干净,自然会想:退回到某个合适的提交点,重新整理内容,再干干净净地推送一次 ✨。

下面就用一个简单示例,来演示如何安全地完成这个过程。


🧭 1. 查看当前历史,确认回退目标

git log --oneline -3

假设输出如下:

9a3a0ec (HEAD -> master, origin/master, origin/HEAD) Create 测试3.txt
2908bea Create 测试2.txt
8d8a615 Create 测试1.txt
  • 想回退到 2908bea(上一个提交) → 可用 2908beaHEAD~1
  • 想回退到 8d8a615(再上一个提交) → 可用 8d8a615HEAD~2

💡 小技巧:HEAD~n 表示当前提交往前数第 n 个提交,非常方便!


⏪ 2. 在本地执行回退

使用 git reset 有三种模式,效果不同,按需选择 👇:

📌 使用相对引用(以回退到 2908bea 为例)

git reset --soft HEAD~1    # 回到 2908bea,9a3a0ec 的改动保留在暂存区(已 add,未 commit)
git reset --mixed HEAD~1   # 回到 2908bea,9a3a0ec 的改动变成“未暂存的修改”(已修改,未 add)
git reset --hard HEAD~1    # 回到 2908bea,9a3a0ec 的改动彻底丢弃 ⚠️(危险操作!)

📌 使用具体提交哈希(与上面效果完全相同)

git reset --soft 2908bea
git reset --mixed 2908bea
git reset --hard 2908bea

💡 如何选择?

  • 若想重新修改提交信息或补文件后再提交 → --soft
  • 若想重新选择哪些文件要提交(重新 add)→ --mixed
  • 若这些改动完全没用了 → --hard 🗑️

🚀 3. 强制推送到远程

现在你的本地仓库已经“倒退”了(假设远程还停在 9a3a0ec),普通 git push 会被拒绝。

你需要明确告诉 Git:“我就是要用本地覆盖远程!” 🌊

务必使用更安全的强制推送命令:

git push --force-with-lease

✅ 这个命令会先检查远程分支是否还是你上次拉取时的状态,如果没有其他人在此期间推送了新内容,才允许覆盖。

这样就可以避免误伤队友的提交,比 git push -f 安全太多 👍。

如果这是你个人独享的分支,而且你完全确定没有其他人改动,也可以使用 git push -f,但推荐把 --force-with-lease 培养成肌肉记忆 💪。


🔍 4. 验证远程是否已更新

git log --oneline -3

确认远程分支的顶端已经是你的目标提交,一切就大功告成啦 🎉。