这篇文章上次修改于 695 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

微服务框架盛行的时代,开发人员希望将各模块解耦,有时会涉及代码仓库的拆分,如将一个大仓库中的某个子目录作为一个新的独立仓库拆分出去。

可以自然想到的两种简单方式:

  1. 把子目录移出代码仓库,在移出的子目录里 git init 创建新仓库 (缺点:新仓库不保留文件历史)
  2. 复制代码仓库,删除子目录以外的其他文件 (缺点: 其他的目录文件还存在于仓库中,git checkout 可查看,而且仓库巨大)

但以上两种方式均不可取,使用 git subtree 命令能够简化这样的操作,使用方法:

git subtree split -P <prefix> [OPTIONS] [<commit>]

假设现有目录仓库如下:

$ /usr/bin/tree.exe -L 1
.
|-- audiosrv
|-- cert
`-- test-client

3 directories, 0 files

$ git branch
* master

仓库只有一个master分支,项目包含了3个目录:audiosrvcerttest-client
现在想把 test-client 目录中的提交分离为一个独立的仓库,可以使用如下命令:

#合成test-client子目录树的历史记录,并将历史记录存放在test-client分支
$ git subtree split -P test-client -b test-client
Created branch 'test-client'
98594285029b886a79c5a19327141f88b4f112a2

$ git branch
* master
  test-client

操作完成后,新建了分支 test-client,该分支中只存在 test-client 子目录树中的文件和历史记录。

然后我们便可以创建一个新的本地仓库,并只将 test-client 分支推送到该仓库。

$ cd ..
$ mkdir temp
$ git init
Initialized empty Git repository in C:/Users/doufu/Desktop/temp/.git/
$ git pull ../audiosrv/ test-client
remote: Enumerating objects: 91, done.
remote: Counting objects: 100% (91/91), done.
remote: Compressing objects: 100% (75/75), done.
remote: Total 91 (delta 24), reused 37 (delta 6), pack-reused 0
Unpacking objects: 100% (91/91), 288.82 KiB | 533.00 KiB/s, done.
From ../audiosrv
 * branch            test-client -> FETCH_HEAD

$ git branch
* master
$ git log -n 3 --pretty=oneline
98594285029b886a79c5a19327141f88b4f112a2 (HEAD -> master) 修复设置休眠无效
55a6dc229b9465464c613f1b05d72de8a9b54625 测试页面1小时
e675f7ced5bb83d9b03626fa0491899f1ac75e8f 替换测试页面timer(默认在页面非活跃变慢)

独立仓库已经分离完成,最后便将 master 分支推送到 GitHub 或私有仓库中。