DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

git --force-with-lease 推送成功,却覆盖了远端新增提交

lease省略预期值时会依赖可变远程跟踪引用,fetch后推送通过不代表新增提交已经整合。审查并保留旧历史,授权改写时固定已审核完整OID。

本地改写了一个分支,远端同时被同事或 CI 加入了新提交。第一次推送提示 stale info,刷新远端状态后再用 --force-with-lease 推送却成功了,远端新增提交不再出现在分支上。这个选项没有替你合并那些提交:省略预期值时,它通常用本地的远程跟踪引用作为比较依据,而 fetch 可以更新这个依据。

下面按 Git 2.56.0 的正式参数规则说明。这是推送条件的边界,不足以判断某个 GUI 或分支管理工具当前版本是否已经修复了自己的操作流程。

fetch 更新了引用,不代表本地已经整合

假设本地 origin/topic 记录提交 A,远端已经推进到 B,而你的改写结果 C 没有保留 B 的新增工作。默认 lease 用 A 与远端 B 比较,可以拒绝这次覆盖。

随后一次 fetch 把本地 origin/topic 更新为 B,却没有把 B 整合进本地分支。再次省略预期值使用 lease,比较的是 B 与 B,检查可以通过,远端分支便可能被改为 C。

编辑器后台抓取、定时抓取和工具内部的 fetch,都可能影响远程跟踪引用。推送退出码为零只能证明更新被接受,不能证明新增工作已经保留。

先核对真实推送目标与提交图

停止重复推送,保存本地改写前后的提交入口,以及可找到的远端独有提交。保留引用只能保住提交入口,未提交文件仍需单独备份。

在真正执行推送的仓库中检查目标与已有引用,例如:

git status --short
git remote get-url --push origin
git config --get-all remote.origin.fetch
git log --graph --oneline --decorate HEAD refs/remotes/origin/topic

远程名和分支名要替换为实际值,分享输出前去掉 URL 中的凭据。还要核对 wrapper、GUI 或脚本实际使用的推送参数,是否自动抓取、推送多个分支,或额外加入了强制选项。

本地提交图只反映已经取得的对象。需要更新远端视图时,先记录并保留已有引用,再抓取供审查;不能把刚更新到的 tip 直接当成“我已接受覆盖这个状态”。逐项审查远端独有的修改,按团队流程整合、重放或明确决定如何保留。历史没有改写需求时,采用正常的整合与普通推送。

必须改写共享历史时,固定已经审核的预期值

只有团队明确允许这次历史改写,且已备份并审核要替换的远端状态,才使用明确的 lease 预期值。预期值应在改写之前记录并保留,使用完整 OID,不能临时查询当前 tip 只为了让推送通过。

以下是参数结构,KNOWN_AUDITED_OLD_OID 不是可直接运行的提交 ID:

git push \
  --force-with-lease=refs/heads/topic:KNOWN_AUDITED_OLD_OID \
  origin HEAD:refs/heads/topic

这表示只在远端 refs/heads/topic 仍等于那个已审核状态时,允许把它更新成当前 HEAD。完整分支名、推送身份和本地目标都要核对,仍需遵守分支保护、审批和检查要求。

显式 OID 可以避免比较依据随着远程跟踪引用悄悄移动,但不会检查 C 是否正确保留了 A 的内容,也不会替你证明重放结果符合业务要求。这个判断必须来自实际的差异审查和项目检查。

远端继续推进时,收到 stale info 是应该停止推送、重新审查的信号。保留新旧历史,重新理解新增工作,按协作流程整合;不要再次 fetch 后立刻把新 OID 填进同一条覆盖命令。

其他选项有不同的保护范围

--force-if-includes 可辅助不指定预期 OID 的 lease,用本地分支 reflog 的可达性检查远程跟踪更新是否已被整合。它不是自动合并,也不能代替代码审查。与显式的 --force-with-lease=<refname>:<expect> 同用时,它是 no-op,不能再算一层额外保护。

不要同时加入 --force。它会绕过 lease 检查;带 + 的强制 refspec 也不应作为这项流程的补救。

独立的推送 remote 可以减少某个只抓取 origin 的后台任务对跟踪引用的影响,但运行 fetch --all 仍会更新它。它也不能把未审核的新提交自动变成可以覆盖的内容。

已经覆盖之后,先找回入口再讨论恢复

分支 tip 被改写,不等于原提交对象立刻被物理删除。其他克隆、CI 日志、已有保留引用和仍有效的 reflog 可能保存提交 ID,但不能保证每个平台都允许从这些入口恢复。

尽快记录可找到的完整 OID,保留本地对象和未提交文件,核对覆盖范围并与协作者确认恢复方案。不要再用一次强制推送把“找回提交”与“覆盖当前分支”混在一起;当前远端可能已经有更新的工作。

完成修复后,核对服务器上的目标分支、必须保留的提交及其内容,确认 CI 生成的文件也仍符合预期。验证整个工具下一次推送的取值顺序和实际参数,不能仅凭某次 lease 推送成功宣布流程可靠。