rebase 之后 git push 被拒绝怎么办
rebase 改写了提交历史(哈希全变),与远程分支产生分歧,Git 拒绝推送是保护机制。个人功能分支用 git push --force-with-lease 安全强推;共享分支不要 rebase,改用 merge。
这是正常的保护机制:rebase 会重写历史(所有提交哈希改变),你本地的分支与远程的旧历史产生分叉,Git 为防止覆盖远程提交而拒绝。如果这个功能分支只有你自己在用,用 git push --force-with-lease 强推即可;共享分支请改用 merge,不要 rebase。
安全强推
git push --force-with-lease
--force-with-lease 比 --force 安全:它在推送前检查远程分支是否还是你上次 fetch 时的样子——如果这期间有人推了新提交,推送会被拒绝而不是悄悄覆盖别人的工作。
为什么 rebase 后必须强推
rebase 前(远程): A---B---C feature
rebase 后(本地): A---B---C' feature(C' 是新哈希)
本地和远程的 feature 已经"分叉"。普通 push 要求快进(fast-forward),历史被改写后不可能快进,只能强制覆盖远程。
什么情况不要强推
- 分支有其他人协作(强推会把别人的工作冲掉);
- main/master、release 等受保护分支(GitHub 通常也禁止强推);
- 不确定时:换 merge 策略重来。
常见问题(FAQ)
Q:强推后同事的本地分支会怎样?
他们 pull 时会遇到历史分叉,可能需要 git reset --hard origin/feature 重置。这就是共享分支不该 rebase 的原因。
Q:--force-with-lease 也失败怎么办?
说明远程有你本地不知道的提交。先 git fetch,git log HEAD..origin/feature 看看是什么,确认可以丢弃再强推,或者 merge 进来。
Q:想保持干净历史又怕强推,有折中吗?
有:rebase 只在合并回 main 之前对纯个人分支做;合并用 GitHub 的 "Squash and merge",既得到线性历史又无需强推共享分支。