Git Push 被拒绝:remote contains work that you do not have locally 的原因与解决方案
摘要
在使用 Git 将本地代码推送到 GitHub 时,有时会遇到 fetch first 或 remote contains work that you do not have locally 的错误。这个问题并不是代码写错了,而是因为远程仓库已经有了本地没有的提交。本文结合一次真实的 GitHub Pages 项目推送过程,完整分析问题原因、解决流程以及注意事项。
一、问题现象
在本地完成个人网站修改后,执行推送命令:
git push origin main
结果出现如下错误:
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'https://github.com/账号名字/账号名字.github.io.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally.
核心提示是:
remote contains work that you do not have locally
也就是说,远程仓库里有一些本地没有的提交。
二、为什么会出现这个问题?
这个问题的本质是:
本地分支和远程分支的提交历史不一致。
比如本地提交历史是:
A -- B -- 本地新提交
但 GitHub 远程仓库已经变成:
A -- B -- C -- D -- E
此时本地直接 push,Git 会担心你覆盖远程已有提交,所以拒绝推送。
常见原因包括:
- 在 GitHub 网页上编辑过文件。
- 在 GitHub 网页上传过文件。
- 另一台电脑或另一个本地目录推送过代码。
- GitHub Actions 自动生成并提交过文件。
- 本地仓库很久没有同步远程仓库。
三、如何确认当前状态?
可以先执行:
git status --short --branch
如果看到类似:
## main...origin/main [ahead 1, behind 12]
说明当前分支状态是:
ahead 1:本地比远程多 1 个提交。behind 12:远程比本地多 12 个提交。
这就是典型的本地和远程分支分叉。
四、推荐解决方案
1. 拉取远程最新记录
先执行:
git fetch origin
fetch 只会把远程最新提交信息拉到本地,不会直接修改当前工作区,比直接 pull 更安全。
2. 使用 rebase 整理提交历史
执行:
git rebase origin/main
这一步会把本地提交移动到远程最新提交之后。
变基后的提交历史类似:
A -- B -- C -- D -- E -- 本地新提交
这样提交历史会更清晰。
3. 如果没有冲突,直接推送
git push origin main
五、如果 rebase 出现冲突怎么办?
有时执行:
git rebase origin/main
会出现冲突,例如:
CONFLICT (content): Merge conflict in index.html
CONFLICT (content): Merge conflict in assets/js/main.js
error: could not apply xxx...
这说明本地和远程都修改了同一个文件的同一部分,Git 无法自动判断该保留哪一份。
1. 查看冲突文件
git status
或者:
git diff --name-only --diff-filter=U
2. 打开冲突文件
冲突内容通常长这样:
<<<<<<< HEAD
远程分支中的内容
=======
本地提交中的内容
>>>>>>> commit-id
需要手动选择保留哪部分,然后删除这些冲突标记:
<<<<<<< HEAD
=======
>>>>>>> commit-id
3. 标记冲突已解决
git add 冲突文件路径
例如:
git add index.html assets/js/main.js assets/css/main.css
4. 继续 rebase
git rebase --continue
如果还有冲突,继续重复上述步骤,直到 rebase 完成。
六、最终推送
rebase 完成后,再次查看状态:
git status --short --branch
如果看到:
## main...origin/main [ahead 1]
说明本地已经基于远程最新代码,只多了一个本地提交。
此时执行:
git push origin main
即可成功推送。
七、完整命令流程
git status --short --branch
git fetch origin
git rebase origin/main
# 如果出现冲突,手动解决后执行:
git add .
git rebase --continue
# rebase 完成后推送:
git push origin main
八、不要轻易使用 git push -f
有些人遇到 push 被拒绝后,会直接使用:
git push -f origin main
这非常危险。
git push -f 会强制覆盖远程分支,可能导致远程已有提交丢失。
除非你非常确定远程提交可以被覆盖,否则不要在重要仓库中随意使用强制推送。
九、额外提示:TLS certificate verification has been disabled
推送时还可能看到这样的警告:
warning: TLS certificate verification has been disabled!
warning: HTTPS connections may not be secure.
这个警告不是 push 被拒绝的原因。
它表示 Git 的 HTTPS 证书校验被关闭了,存在安全风险。
可以执行:
git config --global http.sslVerify true
然后检查配置:
git config --get --show-origin http.sslVerify
如果仍然显示为 false,说明还有其他配置文件覆盖了这个设置,需要继续排查。
十、总结
这次问题的本质是:
远程仓库有本地没有的提交,本地又有新的提交,导致 Git 无法直接 push。
正确处理思路是:
- 先使用
git fetch origin获取远程最新提交。 - 再使用
git rebase origin/main把本地提交接到远程最新提交之后。 - 如果出现冲突,手动解决冲突。
- 最后执行
git push origin main推送。
一句话总结:
Git push 被 rejected,不代表代码有问题,大多数时候只是本地分支没有同步远程最新提交。
更多推荐


所有评论(0)