git push --force 会用本地 commit 链完全替换远程分支 ref,导致被跳过的提交被 git gc 彻底清除;应优先使用 --force-with-lease 并配合 git fetch,协作分支强制推送前须同步团队并检查 ci 状态。

git push --force 会直接删掉远程分支的历史记录
这不是“覆盖新提交”,而是用本地分支的 commit 链完全替换远程分支的 ref。远程仓库里被跳过的那些 commit 如果没人拉过、也没被其他分支引用,几小时后就会被 git gc 清掉——彻底找不回来。
常见错误现象:! [rejected] main -> main (non-fast-forward) 出现后,有人顺手加 --force 就推,结果团队其他人 git pull 直接报错,甚至本地 git log 看到的提交突然“消失”。
- 仅限自己独占的分支(如
feature/xxx-wip)或刚建好、确认无人基于它开发的分支 - 如果远程分支有他人协作痕迹(比如 CI 已基于某次 push 构建过),先在群里同步,再操作
- 永远优先考虑
git push --force-with-lease,它会检查远程 ref 是否被别人更新过,避免误覆盖
git push --force-with-lease 不是“安全模式”,它只防别人推,不防你自己删
--force-with-lease 的原理是:推送前比对本地记录的远程 HEAD(即上次 git fetch 时知道的值)和真实远程值。一致才允许强制推送。
但它不会阻止你用 git reset --hard 回退后又强制推——因为本地记录的远程 HEAD 还没更新,它以为“没人动过”。所以这个参数防的是“别人并发改”,不是“自己反复折腾”。
- 执行
git push --force-with-lease前,确保刚做过git fetch,否则本地缓存的远程位置可能已过期 - 如果提示
! [rejected] ... (stale info),别硬加--force,先git fetch再重试 - CI/CD 流水线里慎用——某些平台 fetch 行为不透明,
--force-with-lease可能意外失败
重写历史后强制推送,别人要怎么恢复本地分支
一旦你 push --force 了,合作者的本地 main 分支就和远程不一致了。他们不能直接 git pull,因为 Git 默认拒绝非快进合并。
最稳妥的做法不是“覆盖自己”,而是“重设到远程”:
- 运行
git fetch origin拉取最新远程状态 - 运行
git reset --hard origin/main(把本地main强制指向远程当前HEAD) - 如果本地有未提交修改,先
git stash,reset 后再git stash pop - 切忌用
git merge origin/main或git rebase origin/main——这会在本地多出重复提交,后续更难清理
GitHub / GitLab 上 protected branches 会拦住所有 force push
默认开启保护的分支(如 main、master)会禁止任何 --force 操作,哪怕你是仓库管理员。这不是 Git 本身的限制,是平台级防护。
想绕过?不行。但可以临时调整设置:
- GitHub:Settings → Branches → Branch protection rules → 找到对应规则 → 取消勾选
Include administrators(不推荐),或临时禁用整条规则(需 Owner 权限) - GitLab:Settings → Repository → Protected branches → 编辑对应分支 → 把
Allowed to force push设为Yes(同样需 Maintainer 权限) - 改完立刻恢复保护——这是唯一能防止误操作的手段
真正麻烦的从来不是命令怎么敲,而是你 push --force 之后,得挨个通知队友重置本地分支,还得确认 CI 是否重新触发、部署是否回滚、监控告警有没有乱报。这些事没法靠 --force-with-lease 自动解决。











