Git submodules allow you to include and manage a Git repository as a subdirectory within another Git repository. This is especially useful when your project depends on external libraries or projects. With submodules, you can keep your project and the external dependencies separate yet connected, ensuring that your project points to specific versions of external repositories.
This also allows you to update and maintain these dependencies individually, without altering the commit history of the parent repository.
Introduction to Git submodules
A submodule in Git is essentially a marker within a parent repository, pointing to a specific commit in another repository. This setup allows you to track external repositories within your project. When someone clones your repository, the submodules are not automatically cloned; instead, specific steps need to be followed to initialize and update the submodules.
Adding a submodule to your project
To add a new submodule to your project, use the git submodule add
command followed by the repository URL and the path where you want the submodule to reside within your project.
Example:
git submodule add <https://github.com/example/lib.git> external/lib
This command clones the lib
repository into the external/lib
directory of your project and adds a new entry in a special file named .gitmodules
, which tracks your submodules.
Cloning a repository with submodules
When you clone a repository that contains submodules using git clone
, the submodules directories are empty. To clone a repository and automatically initialize and update its submodules, use the --recurse-submodules
option.
Example:
git clone --recurse-submodules <https://github.com/example/project.git>
If you've already cloned a repository without its submodules, you can initialize and update them with:
git submodule update --init --recursive
This will initialize your repository with the latest version of the submodules, allowing you to compile and build, leveraging these dependencies.
Working with submodules
Updating submodules: To update a submodule to the latest commit on its tracked branch, use
git submodule update --remote
. This command fetches the latest changes in the submodules' remote repositories and updates your local submodule to point to the latest commit.Checking out a branch in a submodule: Sometimes, you may need to work on a specific branch of a submodule. First, change to the submodule's directory, then check out the desired branch:
cd external/libgit checkout experimentalv0
In this example we navigate to our submodule external/lib
and checkout the experimentalv0
branch. This way we can test the latest non-stable version of the dependency without making changes to our actual project’s repository.
- Adding Changes to a Submodule: If you make changes within a submodule, you'll need to commit those changes within the submodule's directory and then commit the updated submodule reference in the parent repository, as the submodule tracks its history independent of the parent project.
Managing submodule changes
When you update a submodule, the parent repository notices the change to the submodule's commit pointer. To include this update in your project, add and commit the change in the parent repository:
git add external/libgit commit -m "Update submodule to latest version"
This process ensures that other developers working on your project can sync their submodules to the same commit.
Advanced submodule management
Listing submodules: Use
git config --file .gitmodules --name-only --get-regexp path$
to list all submodules in your project.Fetching updates for all submodules: The
git submodule update --remote
command can be used to fetch and update all submodules according to the branch specified in.gitmodules
.Checking out submodules recursively: If your submodules have their own submodules, use
git submodule update --init --recursive
to recursively initialize and update them.
Troubleshooting and tips
Submodule 'not a git repository' error: If you encounter this error, ensure you've initialized your submodules with
git submodule update --init
.Force pulling submodule changes: To force-update a submodule to reflect the commit specified in the parent repository, use
git submodule update --init --recursive
.
For further reading on git submodules see the official git documentation.