本地 rebase 完准备推,终端甩出一行 ! [rejected] main -> main (non-fast-forward),旁边同事头也不抬:加个 -f 就行了,这就是 git push -f。

-f 是 --force 的缩写。它让远端分支直接指向你本地这个提交,不检查中间有没有别人的提交,也不弹确认,推上去立刻生效。普通 push 被拒,是因为远端有你本地没有的提交,Git 怕覆盖,强推就是把这个保护关掉。

被覆盖的到底是什么

远端原来有几个提交不在你的历史里,强推之后它们从分支上消失。提交对象一般还在仓库里,但没有分支指向,过段时间被回收就真没了。同事基于旧提交改的代码,下次 pull 会撞出一堆冲突。

更麻烦的是持续集成。流水线已经按旧提交跑过一轮,强推后提交号全变,构建记录对不上,回滚时找不到对应的包。

强推只影响你指定的那一个分支,别的分支不动。命令里分支名写错,覆盖的就是另一个分支,敲回车之前看两遍。

哪些情况可以接受

  • 分支是你自己开的,确认没有第二个人在使用
  • 刚做完 rebase 或 amend,只是整理自己的提交
  • 远端是个人备份仓库,不参与协作

main、master、release 这类共享分支,任何时候都别强推。正规团队一般会给这些分支开保护,普通成员根本没有强推权限。真推了会报 protected branch 之类的错误,找管理员也没用,规则就是不让改。

更稳的写法

git push --force-with-lease origin 分支名

它会核对远端当前提交是不是你上次看到的那一个,别人推过新内容就拒绝,比 -f 多一道保险。团队里推功能分支,建议默认用它。前提是你先 fetch 过,本地记录的远端状态才是新的。

推错了怎么补救

本地 git reflog 还能翻到旧提交,从那里拉一个恢复分支重新推上去,然后在群里说一声,让别人先别动。拖得越久,找回来的成本越高。要是同事已经 pull 过旧历史,让他 reset 到新分支,别直接 merge。

git push -f 改的是历史,不是错误;能用普通 push 解决的,别动它。