git push --force-with-lease 是带远程状态校验的安全强制推送,仅当远程分支自上次 fetch 后未被更新时才允许覆盖;而 git push -f 无条件强行改写,极易覆盖他人提交导致协作灾难。

git push --force-with-lease 是什么,为什么不能直接用 git push -f
它不是“更温和的强制推送”,而是带校验的覆盖操作:git push --force-with-lease origin main 会在推送前检查远程 main 分支自你上次 git fetch 后是否被他人更新过。如果已被更新(比如同事刚推了新提交),命令会失败并报错,而不是静默覆盖。
而 git push -f(等价于 git push --force)完全跳过这层检查,只要权限够就强行改写远程 ref,哪怕别人已基于旧 commit 做了三天开发,也会被连根拔掉。
- 本地没
fetch过?--force-with-lease会当作“没人动过”,允许推送 —— 这是合理默认行为 - 你刚
git pull完,同事又立刻推了一个提交?下次--force-with-lease就会拒绝,逼你先git fetch看差异 - 想绕过这个保护?可以用
--force-with-lease=<refname>:<expect></expect></refname>手动指定期望值,但几乎没必要,反而容易出错
什么时候必须用 --force-with-lease,而不是 git push 普通推送
普通 git push 只允许 fast-forward 合并,一旦本地分支历史被重写(比如 git rebase -i、git commit --amend、git filter-repo),就会被拒绝。这时必须用带 lease 的强制推送来同步新历史。
- 你刚用
git rebase -i HEAD~3整理了最近三次提交,想把干净历史推到远程main:用git push --force-with-lease origin main - 误提交了
.env文件,用git rm --cached .env && git commit --amend删除后,需强制更新远程最新 commit - CI/CD 流水线生成的临时分支(如
ci-build-123),只供机器读取,无协作风险,可放心用--force-with-lease - 别对
main、develop这类共享主干分支执行任何 force 操作,除非团队明确约定且全员知晓
远程分支被保护(protected branch)时,--force-with-lease 也推不过去
GitHub/GitLab/Gitee 上启用分支保护后,即使你本地命令正确、权限足够,git push --force-with-lease origin main 仍会返回 403 或类似错误,例如:
remote: error: GH006: Protected branch update failed for refs/heads/main.
这不是 Git 本身的问题,而是远端服务策略拦截。此时你有两个选择:
- 联系管理员临时禁用该分支的 force push 限制(仅限紧急修复)
- 改用
git revert回退问题提交,走常规 PR/MR 流程 —— 这才是生产环境的合规做法 - 确认你推的是正确分支名;有时本地叫
master,远程其实是main,写错会导致推送被拒绝或推到错误位置
协作者拉取被 force 推送过的分支时,该怎么同步
他们执行 git pull 会失败,提示 non-fast-forward 或 refusing to merge unrelated histories。这不是 bug,是 Git 在防止他们把旧历史再推回来。
正确做法是丢弃本地旧分支,硬重置为远程新历史:
git fetch origin<br>git reset --hard origin/main
注意:--hard 会彻底丢弃工作区和暂存区所有未提交更改,务必提前备份重要修改。
如果本地有未 push 的新提交,又想保留它们,就不能直接 reset,得先 git stash 或新建分支保存,再考虑 rebase 到新基线上 —— 这步容易出错,建议在测试分支上先演练。


















