Watch at Ease看见世界,读懂生活。

科技 · 实用指南

Git push 因 non-fast-forward 被拒?修复前先证明远端引用

拒绝是图结构安全信号,不是要求强推。先确定目标引用与当前 OID,再抓取审计副本,最后选择合并、变基或经批准的明确 lease。

原创示意图:共同基点、远端 tip 与本地 tip 形成 non-fast-forward 图。
原创示意图:共同基点、远端 tip 与本地 tip 形成 non-fast-forward 图。 Watch at Ease

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 改变意味着审过的条件已失效,应重新检查。

原创示意图:从目标解析到按策略整合或改写的五步流程。
原创示意图:从目标解析到按策略整合或改写的五步流程。 Watch at Ease