Git Submodules
Submodules let one Git repository embed another repository at a fixed commit, useful for pulling in a shared library while keeping its history separate from your own project's.
What a Submodule Is
A submodule is a reference inside your repository that points to a specific commit in another repository. Instead of copying that other project's files into yours, Git stores a pointer: the submodule's URL and the exact commit hash it should be checked out at. This means your main repository's history doesn't grow with every change in the dependency, and the dependency keeps its own independent commit history.
Submodules are commonly used for shared component libraries, vendored dependencies without a package manager, or documentation repositories that need to travel alongside several projects.
Adding a Submodule
Use git submodule add with the URL of the repository you want to embed and, optionally, the local path where it should live. Git creates a .gitmodules file at the repository root recording the mapping between path and URL.
Add a submodule
$ git submodule add git@github.com:org/shared-ui.git libs/shared-ui
Cloning into 'libs/shared-ui'...
remote: Enumerating objects: 340, done.
Resolving deltas: 100% (120/120), done.
$ git status
new file: .gitmodules
new file: libs/shared-uiCloning a Repository That Has Submodules
A plain git clone does not automatically download submodule contents; it only creates empty directories where they belong. You need an extra flag or command to actually populate them.
Clone with submodules included
$ git clone --recurse-submodules git@github.com:org/main-app.git
Cloning into 'main-app'...
Submodule 'libs/shared-ui' (git@github.com:org/shared-ui.git) registered
Submodule path 'libs/shared-ui': checked out '9f2a1c4'If you already cloned without that flag, run the initialize-and-update pair instead of re-cloning from scratch.
Populate submodules after a plain clone
$ git submodule init
$ git submodule update
Submodule path 'libs/shared-ui': checked out '9f2a1c4'Updating a Submodule to a Newer Commit
Moving a submodule forward is a two-step change: first update the submodule's own checkout, then commit that new pointer in the parent repository so everyone else picks it up on their next pull.
- cd into the submodule directory
- git pull origin main (or checkout a specific tag/commit)
- cd back to the parent repository root
- git add path/to/submodule to stage the new pointer
- git commit -m "Update shared-ui submodule to latest"
Pulling Updates Across a Whole Project
When teammates update the submodule pointer, a normal git pull on the parent repository only updates the pointer reference, not the submodule's actual checked-out files. Run the update command with --recursive to sync everything in one pass.
Sync all submodules after pulling
$ git pull
$ git submodule update --init --recursive
Submodule path 'libs/shared-ui': checked out 'a83f9d1'Submodule Commands Summary
Exercise: Git Submodules
What is a Git submodule?