Changing URLs of Git submodules
I prefer using Git over SSH which makes me a minority in most teams I work with. Fortunately, the way I connect to the repository usually doesn't matter, as all Git hosting services support both HTTPS and SSH. Git repositories with submodules are a different story, though.
Git submodules are defined in the .gitmodules
file in the repository. Each submodule definition consists of a path inside the repository where the files from the submodule are placed and a URL of its repository, as in the following example:
[submodule "modules/mySubmodule"]
path = modules/mySubmodule
url = https://github.com/damirarh/mySubmodule.git
The issue with the above example for an SSH user is the absolute HTTPS path. Git can handle that but requires you to authenticate over HTTPS, effectively using two different authentication methods for a single repository.
For an SSH user, a correct configuration would be the following:
[submodule "modules/mySubmodule"]
path = modules/mySubmodule
url = git@github.com:damirarh/mySubmodule.git
Of course, that would cause problems for HTTPS users.
The solution is to use a relative URL instead:
[submodule "modules/mySubmodule"]
path = modules/mySubmodule
url = ../mySubmodule.git
This works for both HTTPS and SSH users because it uses the root repository URL as base onto which the relative path is applied. The ../mySubmodule.git
example would work as long as the parent repository is in the same GitHub organization, e.g. https://github.com/damirarh/myProject.git
or git@github.com:damirarh/myProject.git
. Usually all repositories in a project are at least hosted in the same service, so this technique can be used.
To fix the issue for me (and other SSH users) in repositories which already contain submodules with HTTPS URLs, I have to change the URL. The easiest way I found to do that is as follows:
Modify the URL value in the
.gitmodules
file to make it relative. This file gets committed to Git.Force submodules to resynchronize with the modified file using the following command in the folder with the modified
.gitmodules
file (not necessarily the repository root if its submodules contain other nested submodules):git submodule sync
Update all modules from the now correct remote URL using the following command in the repository root (because it is called recursively on all submodules, even nested ones):
git submodule update --init --recursive --remote
I would recommend using relative submodule URLs whenever possible. They don't force all developers to use HTTPS or SSH leaving them the freedom of choice. Additionally, they will make it easier to migrate your repositories to a different organization or Git host as you won't need to change the submodule configuration for that. You could even have multiple remotes at the same time, all working as expected.