科技 · 实用指南
Git push 因 non-fast-forward 被拒?修复前先证明远端引用
拒绝是图结构安全信号,不是要求强推。先确定目标引用与当前 OID,再抓取审计副本,最后选择合并、变基或经批准的明确 lease。

non-fast-forward 表示目标分支不是拟推送提交的祖先;接受更新会让至少一个远端提交从分支可见历史中消失。第一步应锁定准确目标引用并保存远端 tip,而不是盲目 pull 或 force。
在一次性本地测试中,共同基点为 15c1b740f8f4,远端前进到 ff5235c58d12,第二个克隆产生分叉 tip 220186e6d9a6。普通 push 失败,绑定旧基点的 lease 失败;ls-remote 观察到当前 OID 后,只有明确绑定该值且已授权的测试强推成功。
该测试只证明机制,不代表授权。团队规则、分支保护、PR 规则和远端提交含义决定应整合还是改写。lease 只在写明预期引用值时防止覆盖未见变化,并不会让历史丢失变得合理。
改历史前先确定目标
记录远端 URL、当前分支、upstream 与 push refspec,并写出 refs/heads/main 这样的精确目标。未明确目标前,祖先判断没有意义。
用 git ls-remote --heads origin refs/heads/main 直接查询并保存 OID 与时间。没有返回行就停止核对拼写、权限和引用类型,不要以陈旧 tracking ref 代替。
抓取已观察 tip 并判断图结构
把目标抓到专用 audit ref,确认 OID 与刚才观察值一致,再检查 HEAD...audit/main 两侧独有提交。这样后台 fetch 更新 origin/main 时,已审对象仍保留。
运行 git merge-base --is-ancestor audit/main HEAD。退出 0 表示包含远端 tip;非 0 表示落后或分叉。选择策略前要阅读两侧提交。
共享历史必须保留时进行整合
共享分支应按仓库规则 merge audit ref,或只对未发布本地提交 rebase。解决冲突、测试、复查图后再普通 push。
不要在记录目标与 OID 前盲目 pull;pull 会按配置组合 fetch 与 merge 或 rebase,可能先改变工作分支并抹掉解释拒绝所需的证据。
仅在获批改写时使用明确 lease
维护者明确批准改写后,才把 push 绑定到已审 OID:--force-with-lease=refs/heads/main:<observed-oid>。测试中的旧 lease 被拒,当前 lease 只在一次性仓库内成功。
推送后重新读取目标并记录旧 OID、新 OID、批准和原因。lease 被拒时不可自动刷新重试;OID 改变意味着审过的条件已失效,应重新检查。
