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 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
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
[submodule "my-name"] path = ... url = ...
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.
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).
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.
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.