跳转到正文
文章目录

为什么 git push 会失败?

简单来说,是因为 GitHub 仓库里的代码版本比你电脑上的旧——不对,是新。

这种情况通常发生在:

  • 你在 GitHub 网页上直接修改了文件(比如编辑了 README.md)
  • 你在初始化仓库时勾选了"添加 LICENSE"或"添加 .gitignore",导致远程多了这些文件
  • 其他协作者在你上次 pull 之后提交了代码

Git 的规则是:你必须先同步远程的所有修改,才能上传你自己的修改。


图解:为什么路径分叉了

</> PLAINTEXT
远程 (Remote):  A --> B --> C          ← C 是别人提交的
                          
本地 (Local):   A --> B --> D          ← D 是你刚写的

当远程分支走到了 C,而你的本地还在 B 且想提交 D 时,路径就分叉了。Git 不允许直接覆盖远程的 C。


三种解决方案

✅ 方案一(推荐):变基 git pull --rebase

将远程的新改动"垫"在你的修改之下,提交历史保持一条直线,干净、优雅。

</> BASH
git pull --rebase origin main
git push origin main

🔵 方案二(稳妥):普通合并 git pull

会拉取远程改动,并自动产生一条 Merge branch 'main'... 的合并记录。

</> BASH
git pull origin main
git push origin main

⚠️ 方案三(危险):强制覆盖

仅限个人项目! 确定本地才是最终版本,且不在乎 GitHub 上的改动时使用。

</> BASH
git push origin main --force

深入理解:git pull --rebase 的"移花接木"

为了让你理解得更透彻,把 Git 的提交历史想象成一场火炬接力。

第一步:临时保存

Git 把你本地特有的提交(D)先"摘"下来,存入一个临时区域。

</> PLAINTEXT
本地:  A --> B --> C        (D 被摘走了)
              ↑
         临时区: [D]

第二步:同步远程

Git 把远程的新提交(C)拉取到你的本地。

</> PLAINTEXT
本地:  A --> B --> C

第三步:重新接回(Rebase)

Git 把临时保存的 D "接"在 C 的后面。

</> PLAINTEXT
本地:  A --> B --> C --> D  🎉

对比:Merge vs Rebase

特性 git pull(Merge) git pull --rebase
历史线条 产生分叉再合并,多一条 Merge 记录 一条直线,极其干净
可读性 复杂项目里历史线会像"麻花" 提交顺序逻辑清晰
风险 相对安全 若有冲突需手动处理后执行 git rebase --continue

遇到冲突怎么办?

如果 C 和 D 修改了同一行代码,执行 rebase 后会提示 CONFLICT。此时:

</> BASH
# 1. 手动打开冲突文件,解决 <<<<<<< 标记的冲突内容
# 2. 标记冲突已解决
git add <冲突文件>

# 3. 继续 rebase
git rebase --continue

# 4. 最后推送
git push origin main

总结

git pull --rebase 的本质:把你的修改"挪"到远程最新进度之后,
伪造出一种"我一直是在最新代码基础上开发"的假象。

这正是它让提交历史如此干净的秘密。对于个人项目和团队协作,这都是值得养成的好习惯。


如有疑问,欢迎在评论区留言。

评论

搜索站内内容

输入关键词开始搜索