与 GitHub / Gogs 等代码托管平台不同,Coding 使用项目的概念来组织互相关联但不必交织在一起的代码仓库,例如像这个配合某平台使用的工具集代码库,就包含了 3 个数据同步服务以及 2 个工具的源代码仓库。
在迁移到 Gogs 时,我们可以选择建立 5 个新的代码仓库,在本地副本中 git remote set-url origin <new-git-repo-url> && git push -u origin master
。这样迁移副作用最小,不过对于一个处于归档状态的项目来说,即使用了前缀命名等方法,在一堆仓库中找到需要的那几个也似乎过于繁琐了。
也可以新建一个单一的代码仓库,把原仓库的资料按文件夹粘贴进去,不过这样提交历史就会全部丢失,所有代码的提交人就会变成最终 git push
的那个用户,这对代码考古学来说起码是个 K 级灾难了。(引入 submodule 也无助于解决代码仓库过多的问题。)
本文提供的方法至少可以保留原始仓库中主干分支的提交记录,以提到的这个项目为例,最终的代码仓库将调整为如下结构:
$ tree -L 1 .
.
├── README.md
├── bentusi
├── ioc-sync-api
├── ioc-sync-web
├── token-dispatcher
└── token-requester
首先拉取服务 1 ioc-sync-web
的代码:
git clone git@e.coding.net:ddrpa/ioc-sync-web.git
cd ioc-sync-web
将第二个服务 ioc-sync-api
的代码仓库地址添加为一个 remote 源,-f
参数表示在添加远程端点后立即 fetch。我这里直接使用代码仓库的名字 ioc-sync-api
作为源的名字,因此可以通过 ioc-sync-api/master
引用其主干分支。
git remote add -f ioc-sync-api git@e.coding.net:ddrpa/ioc-sync-api.git
merge 服务 2 ioc-sync-api
的代码,注意添加的参数:
git merge --allow-unrelated-histories --strategy ours --no-commit ioc-sync-api/master
创建单独的服务 2 目录 ioc-sync-api/
,把服务 2 相关的代码移入,提交上述变更:
mkdir ioc-sync-api
git read-tree --prefix=ioc-sync-api/ -u ioc-sync-api/master
git add --all && git commit -m "ioc-sync-api-migrated"
现在这个目录的结构类似服务 1 的仓库中增加了一个服务 2 目录。如法炮制,处理剩下 3 个代码仓库,你甚至可以写一个 shell function 来免去输入这些字符的麻烦。
git remote add -f bentusi git@e.coding.net:ddrpa/bentusi.git
git merge --allow-unrelated-histories --strategy ours --no-commit bentusi/master
mkdir bentusi
git read-tree --prefix=bentusi/ -u bentusi/master
git add --all && git commit -m "bentusi-migrated"
...
最后创建服务 1 的文件夹 ioc-sync-web/
,把服务 1 的资源文件移入(排除 .git
和 .gitignore
)。
mkdir ioc-sync-web
mv src ioc-sync-web/
...
合并各个子项目下的 .gitignore
配置,有相对路径的也要处理:
cat bentusi/.gitignore >> .gitignore
...
编写整个项目的 README.md
文件,最后变更项目的 origin 地址为新仓库的地址,提交代码。
在 Gogs 上可以追踪之前提交的 commit: