Manage git submodules with add, update, remove, and list operations. Part of the DevTools Surf developer suite. Browse more tools in the Developer Utilities collection.
Use Cases
Add a shared library or configuration repository as a submodule to multiple services.
Update all submodules to their latest commits as part of a dependency update workflow.
Remove a submodule that has been vendored or migrated into the main repository.
Debug a broken submodule reference after a repository was cloned without --recursive.
Tips
Pin submodules to a specific commit, not a branch — submodules tracking a branch silently drift as the branch is updated, causing non-reproducible builds.
Run git submodule update --init --recursive after cloning a repository with submodules — new contributors who omit this step get empty submodule directories with confusing errors.
Use git submodule foreach to run a command across all submodules: git submodule foreach git pull origin main updates all submodules in one command.
Fun Facts
Git submodules were introduced in Git 1.5.3 (2007), one year after Git itself was created by Linus Torvalds. They were controversial from the start due to their complex mental model.
The git subtree command (introduced in 2012) is an alternative to submodules that stores external code directly in the parent repository history, avoiding the dual-repository complexity at the cost of a more complex merge workflow.
Many large projects have moved away from git submodules toward monorepos (single large repositories) or package managers, citing the operational complexity of keeping submodule references synchronized across teams.
FAQ
How do I update a submodule to the latest commit?
Run git submodule update --remote <submodule-path> to fetch and check out the latest commit from the submodule's remote. Then commit the updated .gitmodules reference in the parent repository.
Why is my submodule directory empty after cloning?
Cloning a repository does not automatically initialize submodules. Run git submodule init followed by git submodule update, or use git clone --recurse-submodules when initially cloning.