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 checkoutcherry-pick
两个分支已完全独立(不同基线) 不要合并,考虑重构或保持独立
测试合并效果 先在临时分支上尝试:git checkout -b test-merge,再执行合并
相关推荐
master3361 小时前
GitLab (Docker) 常用命令及解决方案清单
docker·容器·gitlab
2601_961875241 小时前
花生十三资料网盘|百度云|下载
数据库·windows·git·svn·eclipse·github
qq_356408662 小时前
GitLab 单机私有化部署文档(基于 Docker 环境)
docker·gitlab
小香猪66882 小时前
Git 日常操作完全指南:提交、冲突、分支、账户配置一站式教程
git
OsDepK13 小时前
移动编程OSMDE随时命令行进行Git
ide·git
小李不困还能学1 天前
用git GUI往远程仓库中添加文件/文件夹
git
失途老马1 天前
Git Patch 生成与应用完整操作手册
git
李白的天不白1 天前
下载smartadmin框架
git·github