git push被拒绝主因是本地与远程分支历史不兼容,需先git pull同步再推送;常见于他人已推送新提交、本地amend/rebase/reset导致分叉,错误提示含non-fast-forward等关键词。

远程拒绝推送(push rejected)90% 的情况不是权限或网络问题,而是本地分支和远程分支提交历史不兼容——必须先同步再推送,不能跳过 git pull 或 git fetch 直接硬推。
为什么 git push origin main 报 non-fast-forward
Git 拒绝推送的核心判断是:远程分支最新提交不在你的本地分支历史中。比如别人刚 push 了新 commit,而你本地还基于旧 HEAD 提交;或者初始化仓库时远程已有 README.md,你没 pull 就直接 commit + push。
错误信息里常带关键词:non-fast-forward、failed to push some refs、Updates were rejected。
- 这不是
Permission denied或Authentication failed,那些错会卡在连接阶段 - 也不是
.git损坏,那会导致status、log等命令也失败 -
refusing to update checked out branch是另一类问题:远程仓库是普通工作目录(非裸仓),需单独处理
用 git pull 同步并解决合并冲突
这是最稳妥、协作中最推荐的做法,等价于 git fetch origin + git merge origin/main。
- 执行
git pull origin main,若提示 conflict,说明你和远程改了同一文件的同一段落 - 用编辑器打开含
和 <code>>>>>> origin/main标记的文件,删掉标记,保留最终要的内容 - 保存后运行
git add,再git commit -m "resolve conflict in README.md" - 最后
git push origin main
注意:不要跳过 commit 这步,否则 Git 不认为冲突已解决。
用 git pull --rebase 避免 merge commit
适合希望保持线性历史的场景,把你的本地提交“重放”到远程最新提交之后。
- 执行
git pull --rebase origin main,它会先fetch再rebase - 遇到冲突时,解决后
git add,再git rebase --continue - 完成后直接
git push origin main,无需额外commit - 如果不确定远程是否有他人依赖你的本地 commit,别用这个;有疑问就优先选默认
git pull
什么时候能用 git push --force-with-lease
它比 --force 安全:仅当远程分支自你上次 fetch 后未被他人更新时才覆盖。
- 只限你完全独占的分支(如
feature/xxx),且确认没人基于它开发 - 绝对不要对
main、dev等共享主干分支使用 - GitHub/GitLab 默认禁止 force-push 到受保护分支,加
--force-with-lease也会被拒绝 - 如果执行时报
stale info,说明远程已有新提交未被你获取,此时应切回pull或rebase
真正容易被忽略的是:强制推送不是“修复手段”,而是“覆盖手段”。一旦用了,其他协作者必须手动重置本地分支,否则后续 pull 会出乱子。











