git push --force-with-lease 比 -f 安全,因它推送前校验远程分支最新状态,不一致则拒绝;而 -f 直接覆盖,可能抹除他人提交。

git push --force-with-lease 为什么比 -f 安全
它不是“温柔版 -f”,而是带状态校验的覆盖操作:推送前会比对本地缓存的 origin/main 指针值和远程实际值。一致才允许写入,不一致就报错 ! [rejected] main -> main (stale info),强制你停下来确认。
而 git push -f 完全跳过这层检查,只要权限够,就直接重写远程 refs/heads/main 文件——哪怕同事刚推完一个紧急 hotfix,也会被无声抹掉。
- 本地没执行过
git fetch origin?--force-with-lease会把远程当作“没人动过”,允许推送(这是合理默认,但隐含风险) - 你刚
git pull完,同事又立刻 push 了一个提交?下次--force-with-lease就会拒绝,逼你先git fetch看差异 - Git 版本低于 1.8.5?该参数不可用,
git --version务必确认
什么时候必须用 --force-with-lease,而不是普通 push
普通 git push 只接受 fast-forward 合并。一旦你本地分支历史被改写(比如 git rebase -i、git commit --amend、git filter-repo),远程就会拒绝,报错 non-fast-forward。
这时 --force-with-lease 是唯一安全的同步方式,前提是它真能拦住误覆盖。
-
git rebase -i HEAD~3整理提交后,想把干净历史推到origin/main:用git push --force-with-lease origin main - 误提交了
.env,用git rm --cached .env && git commit --amend删除后,需更新远程最新 commit - CI/CD 生成的临时分支(如
ci-build-123),只供机器读取,无协作风险,可放心用 - 别对
main、develop这类共享主干分支执行任何 force 操作,除非团队有明确约定且全员知晓
protected branch 下 --force-with-lease 依然失败?这是正常现象
GitHub / GitLab / Gitee 启用分支保护后,即使命令正确、权限足够、lease 校验也通过,git push --force-with-lease origin main 仍会返回 403 Forbidden 或类似错误。
这不是 lease 机制失效,而是平台层拦截:保护规则优先于 Git 协议本身的校验逻辑。
- 必须由管理员临时关闭分支保护,或配置“允许强制推送”白名单(通常需指定机器账户 deploy key)
- CI 流水线里慎用——某些平台 fetch 行为不透明,可能导致本地
origin/main缓存过期,让 lease 检查失效 - VSCode 图形界面根本点不出强制推送按钮,这是硬编码限制,不是设置问题;遇到
Updates were rejected because the tip of your current branch is behind,必须切终端操作
lease 检查失败后,下一步该做什么
报错 failed to push some refs; remote tip is behind 不是终点,而是协作信号:说明有人在你 fetch 之后又推了新东西。
此时直接 git fetch origin,然后用 git log origin/main..main 查看本地独有的提交,再决定是 rebase 还是 merge ——而不是绕过检查去加 --force-with-lease=<refname>:<expect></expect></refname> 手动设期望值,那几乎等于自废防护。
- Agent 自动化场景下,建议分级响应:首次失败记录差异;连续 3 次失败锁定该 Agent 的 git 权限;关键仓库首次失败就触发带 diff 的告警
- 本地
reflog必须保留至少 7 天,它是事故后回滚的唯一依据 - lease 机制防的是“误覆盖”,不是“恶意覆盖”;它也不防你自己反复改历史——这点常被忽略











