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

修改git仓库子模块配置,以支持通过ssh及http两种方式克隆包含子模块的整个仓库。

背景

自己搭建的gitlab服务器设置了同时支持ssh方式和http两种方式访问。
服务器上的一个私有源码仓库 repo1,其使用了同服务器上第三方开源库的镜像作为子模块的仓库 repo2;其中,仓库 repo1 在用户空间 user1 下, 仓库 repo2 在用户组空间 group1 下。
在仓库 repo1 中,使用了 repo2 作为 子模块, .gitmodules 中配置如下:

[submodule "repo2"]
    path = repo2
    url = ssh://git@<server_addr>/group1/repo2.git
    ignore = untracked

在这种配置下,使用ssh方式(git clone --recurse-submodules ssh://git@<server_addr>/user1/repo1.git)克隆仓库正常;
但如果使用http方式(git clone --recurse-submodules http://<server_addr>/user1/repo1.git)克隆,当未配置ssh公钥信息时显然子模块会无法克隆成功:

$ git clone http://<server_addr>/user1/repo1.git --recurse-submodules
Cloning into 'repo1'...
remote: Enumerating objects: 50963, done.
remote: Total 50963 (delta 0), reused 0 (delta 0), pack-reused 50963
Receiving objects: 100% (50963/50963), 40.46 MiB | 91.56 MiB/s
Receiving objects: 100% (50963/50963), 45.61 MiB | 91.51 MiB/s, done.
Resolving deltas: 100% (34381/34381), done.
Updating files: 100% (11845/11845), done.
Submodule 'repo2' (ssh://git@<server_addr>/group1/repo2.git) registered for path 'repo2'
Cloning into 'C:/Users/doufu/Desktop/repo1/repo2'...
git@<server_addr>: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
fatal: clone of 'ssh://git@<server_addr>/group1/repo2.git' into submodule path 'C:/Users/doufu/Desktop/repo1/repo2' failed
Failed to clone 'repo2'. Retry scheduled
Cloning into 'C:/Users/doufu/Desktop/repo1/repo2'...
git@<server_addr>: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
fatal: clone of 'ssh://git@<server_addr>/group1/repo2.git' into submodule path 'C:/Users/doufu/Desktop/repo1/repo2' failed
Failed to clone 'repo2' a second time, aborting

解决

可修改子模块url为相对路径方式解决:

[submodule "repo2"]
    path = repo2
    url = ../../group1/repo2.git
    ignore = untracked

说明:
由于 repo1repo2 在不同的用户控件下,故url相对向上了两级。如果在相同空间下,向上一级即可。
修改为相对路径后,会自动根据所属仓库的连接方式克隆子模块.

思考

子模块跨服务器时,无法通过这种方式解决,是否有其他方法实现呢?