Skip to content

git 多仓库合并

起因

一般来说,git 仓库是不用轻易改动的,但是其中一个管理后台项目拆成了十个 git 仓库,跑项目又要新建一个 project 目录,把这十个仓库克隆到 project 里面,根目录是projec, 底下有 A,B,C...等加起来十个目录,需要放在一起才能跑,并且 readme 没说明怎么跑,仓库也是分开的,不知道总共有几个要clone,导致跑项目都要摸索很久,并且分开增加了提交代码的工作量,假设一次改五个项目,那么每次合代码都会提五个merge,如果不是分开部署,这样的拆分既增加了工作量,又增加了提交代码的风险,因此打算把这十个仓库合并成一个仓库。

方案

要把这十个目录放到一个目录底下,并且是保持原来的目录,简单的仓库 merge 会导致目录打平。

方案一(不推荐)

把所有项目克隆到 project 项目,删掉每个项目的 .git 目录,把 project 项目初始化为 git 仓库,推到远程即可,但是这个方法的缺陷是会丢失所有仓库的commit,这个作为最后的方案,暂不考虑。

方案二

为了方便说明,我们分别用用两个目录A,B示例,合成一个仓库

思路介绍:

  1. 把A,B仓库,克隆名到为 old_project 的文件夹下 一定重新创建文件夹 old_project,不要直接用原来存在的开发目录,后面会对old_project做修改,除非确定不再需要修改原开发目录。
shell
# 创建目录
mkdir project 
cd project
# 克隆仓库
git clone htts://xxx.com/A
git clone htts://xxx.com/B

old_project 的文件夹目录应该如下:

text
old_project
|----A
|----B
  1. 再初始化一个新项目 project,示例 old_project 和 project 是同级目录,这个在后面的路径使用很重要,如果不是同目录,需要清楚这两个目录的层级关系
shell
mkdir project
cd project
# 初始化仓库
git init
# 默认是 master 分支,建议切到一个用来 merge 的分支,误操作后还能重新基于 master 创建分支。

# 设置新仓库的远程源
git remote add origin htts://xxx.com/project

前面步骤比较简单,这时候关键步骤来了,下面的步骤千万不能省略,需要用 git mv 指令对文件进行转移,并且不会丢失 commit 记录。

  1. 回到 old_project 目录,把各个目录下的文件收拢到一个目录,这是必要的步骤
shell
# 进入其中一个子目录
cd old_project/A
git checkout master # 看情况选择自己需要合并的分支 默认master
mkdir A # 没错 再建一个A目录,如果想重命名,可以改
# B目录只要把 两处 A 改成 B 即可
ls -A | grep -wv '.git\|A' xargs -t -I 'file' git mv file A/file
git add .
git commit -m 'chore: A仓库合并'

我们来看一下执行完的文件目录结构:

text
old_project
|--A
|  |-A
|--B
|  |-B

B 仓库重复上述步骤即可,不用推送到远端

  1. 回到项目 project 目录,添加 old_project 作为 project 的源。

添加远程的命令为:git remote add <远程源别名> <远程源地址>

我们平时拉项目的时候,相当于 git remote add origin https://xxx.com/old_project

shell
cd project
# 把A、B仓库添加为远程源,源地址可以是链接,也可以是本地路径
git remote add A ../old_project/A
git remote add B ../old_project/B
# 查看 远程源
git remote -v
# todo 补充 remote 命令结果
git fetch --all

设置了源以后,我们的分支从这个源来创建,回到 project 项目: 分别从刚才的目录创建两个分支

shell
cd project
git checkout -b A origin/A
git checkout -b B origin/B

把本地的 old_project 当做源,创建两个分支,此时对于 old_project 下的文件结构是这样:

text
old_project
|--A
|  |-A
|--B
|  |-B

对于 A 仓库来说,它里面还有一个A目录,B 也是如此,我们要把 A 搬到新项目 project 目录下,就必须对其进行打包为一个目录,否则合并的时候,A,B目录合并到新项目目录会打平A、B的根目录到 project 根目录,造成冲突。

下面开始合并仓库:

shell
git merge A --allow-unrelated-histories 
git merge B --allow-unrelated-histories

--allow-unrelated-histories 这个参数允许无关提交历史合并,两个仓库合并如果没有这个参数,git 是拒绝合并过程的。

最后,再把新仓库的代码提交,push 到远端,就能得到与原来目录相同的仓库啦。

总结

再次总结一下移动的思路,首先是把原来的仓库克隆到一个新的目录,然后把各个仓库的文件收拢到一个目录,然后再把这个目录的文件合并到新的仓库,这样就能得到一个新的仓库了。