如何将含派生仓的多个Git仓库合并为单仓且保留提交历史?
解决Monorepo合并历史且无冲突的方案
直接重写两个仓库的提交历史,让所有提交里的文件都默认位于目标子目录下,再合并就不会出现路径冲突了。具体步骤如下:
1. 克隆并处理仓库A
- 先克隆仓库A的本地副本(避免修改原仓库):
git clone <仓库A的URL> repo-a cd repo-a - 使用
git filter-repo重写所有提交历史,将所有文件移动到A目录下:git filter-repo --to-subdirectory-filter A注:如果你的Git版本低于2.22.0,可能需要单独安装
git-filter-repo工具;若暂时无法安装,可使用废弃但仍能用的git filter-branch替代(不推荐,性能较差):git filter-branch --tree-filter 'mkdir -p A; git mv -k * A' -- --all
2. 同样处理仓库B
- 克隆仓库B的本地副本:
git clone <仓库B的URL> repo-b cd repo-b - 重写历史到
B目录:git filter-repo --to-subdirectory-filter B替代命令(filter-branch):
git filter-branch --tree-filter 'mkdir -p B; git mv -k * B' -- --all
3. 创建新仓库C并合并
- 初始化新仓库:
mkdir repo-c cd repo-c git init - 添加处理后的A作为远程并合并:
git remote add repo-a ../repo-a git fetch repo-a git merge repo-a/main --allow-unrelated-histories - 再添加处理后的B并合并:
git remote add repo-b ../repo-b git fetch repo-b git merge repo-b/main --allow-unrelated-histories
为什么之前的方法会冲突?
你之前的操作是在现有分支上新增一个"移动文件到子目录"的提交,但仓库的历史提交里依然存在根目录下的文件。合并时Git会识别到两个仓库的历史中存在大量路径重叠的文件(比如根目录的README.md、package.json等),因此触发冲突。而重写历史的方式是让所有提交中的文件都默认位于子目录下,两个仓库的文件路径完全不重叠,合并时自然不会有冲突,同时完整保留了所有提交历史。
内容的提问来源于stack exchange,提问作者CrunchyArtie
相关产品推荐
相关产品推荐

