Git 合并两个无共同历史的分支:从报错到解决全记录

实战:合并两个独立开发的 Git 分支,并遇到"fatal: refusing to merge unrelated histories",一步步分析原因并给出解决方案。

目录

一、分支合并

[二、为什么会报错 "unrelated histories"?](#二、为什么会报错 “unrelated histories”?)

三、强制合并:--allow-unrelated-histories

四、合并冲突的现场

五、解决冲突的几种方案

[5.1 通过PyCharm工具解决冲突](#5.1 通过PyCharm工具解决冲突)

[5.2 手动解决冲突(适合文件少的情况)](#5.2 手动解决冲突(适合文件少的情况))

[5.3 放弃合并,回到合并前状态](#5.3 放弃合并,回到合并前状态)

[5.4 使用合并策略自动解决(-X ours / -X theirs)](#5.4 使用合并策略自动解决(-X ours / -X theirs))

[5.5 只选取特定文件或代码](#5.5 只选取特定文件或代码)

总结


一、分支合并

在 GitLab 上有一个项目,包含两个分支:

  • tianjin-cb/sop_cip_maf_v1.4.0_260610

  • longwan-cb/sop_cip_maf_v1.3.8_260605

需求:将 longwan-cb/... 分支的代码合并到 tianjin-cb/... 分支中。

操作步骤很简单:

bash 复制代码
# 克隆目标分支
git clone -b tianjin-cb/sop_cip_maf_v1.4.0_260610 https://gitlab.xxx.com/xxx/sop_engine.git

# 进入目录
cd sop_cip_maf_v1.4.0_260610

# 获取远程所有分支
git fetch origin

# 尝试合并另一个分支
git merge origin/longwan-cb/sop_cip_maf_v1.3.8_260605

如果出现错误:

fatal: refusing to merge unrelated histories

**二、**为什么会报错 "unrelated histories"?

Git 默认要求合并的两个分支有共同的祖先提交 。如果两个分支是基于完全不同的初始提交创建的(比如分别从两个独立的仓库导入,或者用 --orphan 创建的孤立分支),Git 认为它们没有历史关联,直接合并可能会引入不相关的代码,因此拒绝执行。

常见场景:

  • 两个分支分别从不同的远程仓库拉取

  • 其中一个分支是用 git checkout --orphan 创建的

  • 重新初始化了仓库并强制推送,导致历史割裂

在我这个案例中,两个分支很可能由不同的人在不同的时间点基于不同的基线创建,导致 Git 无法找到共同的 commit。

三、强制合并:--allow-unrelated-histories

如果确认需要合并这两个历史无关的分支,可以使用 --allow-unrelated-histories 选项强制 Git 执行合并。

bash 复制代码
git merge origin/longwan-cb/sop_cip_maf_v1.3.8_260605 --allow-unrelated-histories

此时 Git 会尝试合并,但往往会遇到大量冲突,因为两个分支的文件结构和内容可能完全不同。

四、合并冲突的现场

运行上述命令后,终端输出类似:

Auto-merging .gitignore

CONFLICT (add/add): Merge conflict in .gitignore

Auto-merging sop_engine/app/api/v1/sop_validator.py

CONFLICT (add/add): Merge conflict in sop_engine/app/api/v1/sop_validator.py

...

Automatic merge failed; fix conflicts and then commit the result.

冲突类型为 add/add,表示两个分支都新增了同名文件,但内容不同。Git 不知道应该保留哪一个版本,所以标记为冲突,需要人工裁决。

五、解决冲突的几种方案

5.1 通过PyCharm工具解决冲突

使用PyCharm工具打开项目文件,会看到提示合并及其所存在的冲突,

点击那个绿色箭头你就可以看到所有存在更改和冲突的文件:

双击文件你可以进行冲突解决,最左侧的是当前你打开的版本,最右侧的为你要合并进行的版本,中间的为需要应用的版本。

5.2 手动解决冲突(适合文件少的情况)

对每个冲突文件,打开编辑,删除 <<<<<<<、=======、>>>>>>> 标记,保留最终需要的代码。然后:

bash 复制代码
git add <已解决的文件>
git commit -m "Merge longwan branch into tianjin branch"

缺点:冲突文件多(本例中 40+ 个)时非常耗时,且容易出错。

5.3 放弃合并,回到合并前状态

如果觉得手动解决不现实,可以放弃本次合并:

bash 复制代码
git merge --abort

5.4 使用合并策略自动解决(-X ours / -X theirs)

  • 保留当前分支(tianjin)的版本:遇到冲突时自动采用当前分支的文件
bash 复制代码
git merge origin/longwan-cb/... --allow-unrelated-histories -X ours
  • 完全采用被合并分支(longwan)的版本:
bash 复制代码
git merge origin/longwan-cb/... --allow-unrelated-histories -X theirs

这种方式不会弹出冲突编辑,直接按策略选择。但注意:它会丢弃另一方的所有修改,可能不符合预期。

5.5 只选取特定文件或代码

如果并不需要完整合并整个分支,而是希望将另一个分支的某些文件或某些提交 应用到当前分支,建议放弃 merge,改用:

  • 复制单个文件:
bash 复制代码
git checkout origin/longwan-cb/sop_cip_maf_v1.3.8_260605 -- path/to/file.py
git add path/to/file.py
git commit -m "Import file.py from longwan branch"
  • 挑选特定提交 (cherry-pick):
bash 复制代码
git log origin/longwan-cb/...  # 查看需要哪些commit
git cherry-pick <commit-hash>
  • 查看差异后再决定:
bash 复制代码
git diff origin/longwan-cb/... --stat
git diff origin/longwan-cb/... -- <具体文件>

总结

场景 推荐方案
两个分支本应共享历史 使用 --allow-unrelated-histories 合并一次,以后保持共同祖先
只需另一个分支的少量文件 git checkout 或 cherry-pick
两个分支已完全独立(不同基线) 不要合并,考虑重构或保持独立
测试合并效果 先在临时分支上尝试:git checkout -b test-merge,再执行合并
相关推荐
-恰饭第一名-17 分钟前
Codex 任务上下文整理:事实清单、只读检查与开场模板
git
打盹的小pig9 小时前
git pull 报错
git
Tairitsu_H20 小时前
[版本控制器Git] Git 远程仓库 | 多人协作 | 企业级 Git Flow 开发模型
git·版本控制器·远程仓库
我先去打把游戏先20 小时前
Git-Rebase使用指南-从原理到实战
服务器·git·嵌入式硬件·物联网·ubuntu
kaixin_learn_qt_ing1 天前
我有两个程序,它们在不同的项目中,但是它们复用了一部分头文件,它们在两个不同的git仓库中,有什么好的办法可以让它们复用吗?
git
greatofdream1 天前
git rebase时如何解决merge节点冲突问题
大数据·git·elasticsearch
GoodStudyAndDayDayUp2 天前
gitlab私有化跑CICD
gitlab·gitlab私有化跑cicd
敲敲敲-敲代码2 天前
git安装记录
git
我是人✓2 天前
Git入门:从零开始掌握分布式版本控制
分布式·git
成为你的宁宁2 天前
【Gitlab测试项目】
gitlab·devops