Submodules
Submodule Mechanics: Add, Update, Clone
After this page you can attach another Git repository at a path and record which commit it should be.
A submodule is a nested repository plus a gitlink
desk-api might need a shared desk-lib history without merging the trees. A submodule stores a commit hash in the parent tree (a gitlink, mode 160000) and a URL in .gitmodules.
desk-api (superproject)
├── README.md
├── src/ping.py
└── src/desk-lib/ gitlink 160000 → commit 9fceb02 of desk-lib
└── (nested .git)
desk-lib (its own history)
A ← B ← 9fceb02 ← the hash the parent pins
cd ~/desk/desk-api
git submodule add ~/desk/desk-lib src/desk-lib
git status
git commit -m "chore: add desk-lib submodule".gitmodules is a tracked file:
[submodule "src/desk-lib"]
path = src/desk-lib
url = /home/ada/desk/desk-lib
On Linux use an SSH URL for anything you will clone elsewhere (git@host:ada/desk-lib.git). A path only works on this machine.
Clone a superproject
git clone --recurse-submodules <url> desk-api
# or after a plain clone:
git submodule update --init --recursiveWithout --recurse-submodules / update --init, the path exists as an empty directory.
Update the pin
cd src/desk-lib
git fetch
git switch main
git pull --ff-only
cd ../..
git add src/desk-lib
git commit -m "chore: bump desk-lib"The parent records a new gitlink hash. Pulling the parent does not move the submodule until git submodule update.
Pitfalls
- Committing in the submodule and forgetting to push it: the parent points at a hash nobody else can fetch.
- Editing files in
src/desk-libwhile detached:git switch -cin the submodule first. - Nested submodules:
--recursiveon clone and update.
If the team is small and desk-lib changes with desk-api every day, a monorepo (chapter 15) or a copy may hurt less. Submodules shine when the nested project has its own release cycle.