How to manage Git submodules

Greg Foster
Greg Foster
Graphite software engineer

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.

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.

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:

Terminal
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.

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:

Terminal
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:

Terminal
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.

  • 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:

Terminal
cd external/lib
git 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.

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:

Terminal
git add external/lib
git 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.

  • 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.

  • 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.

Stay unblocked. Ship faster.
Experience the new developer workflow - create, review, and merge code continuously. Get started with one command.
Get started

Give your PR workflow
an upgrade today

Stack easier | Ship smaller | Review quicker

Or install our CLI.
Product Screenshot 1
Product Screenshot 2