Git submodules are repositories embedded inside other repositories. According to the docs (git help submodule
), the parent repository is referred to as the "superproject" while the children repositories are called "submodules". A core use case for submodules is dependency management.
Add a submodule
Add a submodule by providing the remote git repo url and the path where you want the submodule stored in your own repo.
git submodule add [git-repo-url] [path]
# git submodule add https://github.com/username/repo ./path/to/submodule
This will create a top-level dotfile in the superproject, .gitmodules
, that contains a list of all the submodules in your superproject. This file will be reference by git to perform later actions. It will look something like:
[submodule "[path]"]
path = [path]
url = [url]
[submodule ...]
...
There will also be an extremely similar changeset in the .git/config
folder.
In case you want to move paths later, I recommend using the --name
flag to give the submodule a name that is unrelated to the path. For example,
git submodule add --name my-name https://github.com/username/repo path/to/submodule
This would change the .gitmodules
,
[submodule "my-name"]
path = ...
url = ...
Cloning submodules
When you first clone a superproject you will not clone the submodules. To clone the submodules run
git submodule init
git submodule update
Or combine them with
git submodule update --init
If submodules themselves contain submodules
git submodule update --init --recursive
All variations of the update command are idempotent so you can run them multiple times without problems.
Updating submodules
We've already seen how to do this above. Run one of the git submodule update
commands above.
If you want to be more surgical in how you update your dependencies, you can jump into each submodule individually. This will place you in the repo, and you can run commands like git status
and git pull
like you would a normal repository (because it is just a normal repository).
Moving submodules within a superproject
git mv path/to/submodule new/path/to/submodule
If you did not use the --name
flag of the submodule add
command, the superproject name of your submodule might still be the outdated path. Check .gitmodules
. You can change the submodule's name manually.
How git tracks submodules
Each submodule has a .git
file (not a folder) that points to a directory inside the superproject's .git/modules/
folder. The path to the git-tracked folder mimics the path to the submodule within the superproject. For example, a submodule at ./a/b/my-submodule/
in the superproject, would have a git-tracked folder at ./.git/modules/a/b/my-submodule/
. That git-internal folder tracks all the regular things git tracks, including the current commit. This is how you can version-lock your dependencies.