场景: 本地项目首次关联 GitHub 仓库时,远程已有文件导致的推送失败
原因分析: 在把本地项目首次推送到 GitHub 时,如果远程仓库在创建时已经自动生成了文件,比如 README.md、LICENSE 或 .gitignore,就很容易遇到"本地和远程历史不一致"的问题。
本文以以下场景为例,完整记录一次处理过程:
- 本地项目目录:
D:\Code\CCleaner - GitHub 仓库地址:
git@github.com:Huazzi/CCleaner.git - 远程仓库在创建时已经添加了
LICENSE - 本地项目也已经有自己的首次提交
一、先把本地项目关联到 GitHub 仓库
进入项目目录:
bash
cd D:\Code\CCleaner
如果当前项目还不是 Git 仓库,先初始化:
bash
git init
查看当前是否已经配置远程仓库:
bash
git remote -v
如果没有输出,说明还没有远程仓库,添加:
bash
git remote add origin git@github.com:Huazzi/CCleaner.git
如果已经有 origin,但地址不正确,可以修改:
bash
git remote set-url origin git@github.com:Huazzi/CCleaner.git
确认远程地址:
bash
git remote -v
正常应看到:
bash
origin git@github.com:Huazzi/CCleaner.git (fetch)
origin git@github.com:Huazzi/CCleaner.git (push)
二、首次推送时报错:fetch first
首次执行:
bash
git push -u origin main
如果远程仓库已经存在提交,就可能出现:
bash
! [rejected] main -> main (fetch first)
error: failed to push some refs to 'github.com:Huazzi/CCleaner.git'
这说明:
- 远程仓库已有提交
- 本地没有这些提交
- Git 不允许直接覆盖远程历史
这时不能直接推送,需要先把远程内容拉到本地。
三、直接 git pull 又提示没有跟踪分支
执行:
bash
git pull
可能会看到:
bash
There is no tracking information for the current branch.
Please specify which branch you want to merge with.
原因是:
当前本地分支 main 还没有和远程分支 origin/main 建立追踪关系。
先确认当前所在分支:
bash
git branch
如果输出:
bash
* main
说明当前就在 main。
然后设置追踪关系:
bash
git branch --set-upstream-to=origin/main main
再查看状态:
bash
git branch -vv
如果出现类似:
bash
* main 9beac7d [origin/main: ahead 1, behind 1] post project files
表示:
- 本地比远程多 1 个提交
- 远程也比本地多 1 个提交
- 两边已经分叉
四、为什么 git pull 仍然失败
此时执行:
bash
git pull origin main --allow-unrelated-histories
可能会出现:
bash
fatal: Need to specify how to reconcile divergent branches.
这是因为新版 Git 在遇到"分叉分支"时,要求你明确指定拉取策略:
- merge
- rebase
- fast-forward only
对于这种"本地和远程各自有首次提交"的情况,最直观稳妥的方式是使用 merge。
五、正确解决方式
直接执行:
bash
git merge origin/main --allow-unrelated-histories
其中:
origin/main:表示把远程main合并到本地--allow-unrelated-histories:允许合并两个原本没有共同祖先的提交历史
如果没有冲突,Git 会生成一个新的合并提交。
然后推送:
bash
git push -u origin main
这样本地和远程就同步完成了。
六、如果出现冲突该怎么办
如果在合并时出现冲突,先查看冲突文件:
bash
git status
手动修改冲突内容后:
bash
git add .
git commit
git push -u origin main
七、最终推荐命令流程
如果你的情况和本文一致,也就是:
- 本地仓库已有提交
- GitHub 远程仓库也已有提交
- 两边是独立初始化的历史
那么可以按下面顺序操作:
bash
git branch --set-upstream-to=origin/main main
git merge origin/main --allow-unrelated-histories
git push -u origin main
八、可选:配置以后 git pull 默认使用 merge
为了避免以后再次出现:
bash
Need to specify how to reconcile divergent branches
可以在当前仓库设置默认拉取策略为 merge:
bash
git config pull.rebase false
如果希望对所有仓库都生效:
bash
git config --global pull.rebase false
之后就可以直接使用:
bash
git pull
九、总结
当本地项目和 GitHub 仓库分别初始化,并且两边都已经有提交时:
- 先建立本地分支与远程分支的追踪关系
- 再将远程历史合并到本地
- 最后推送到远程
最关键的命令是:
bash
git merge origin/main --allow-unrelated-histories
它解决的正是"两个仓库各自有独立起点"的问题。