Submodules
Git submodules provide a means of referencing external dependencies without having to import their history into our repository. Locally, submodules are checked out into the working directory. Submodules track commits directly by their references: they do not track branches. This allows us control over the exact revision we're using.
It's possible to nest submodules, but it's not possible for us to track changes to submodules in the parent repository: we can only point at references which exist upstream. If tracking changes is required, we can copy the history into our repository using worktrees instead.
Configuration
status.submoduleSummary
determines whethergit status
should include the up to date status of submodules or not.push.recurseSubmodules
causesgit push
to push new objects from submodules to their remotes.
Storage
.gitmodules
contains named submodules, with their in-tree paths and remote URLs. It's checked in and versioned alongside our code.- Submodule content is stored in
.git/modules
. - Submodules are linked from their configured
path
to their checkout in.git/modules
.
Fetching
We can have git
recurse into submodules and initialise and update them for us on clone:
git clone --recursive
In an existing repository we can initialise them, then update them:
git submodule init
git submodule update
Or combine both operations in a single command:
git submodule update --init
Add
We can add a module as follows:
git submodule add https://github.com/some-vendor/some-lib.git vendor/some-lib
We must then stage and commit changes to the .gitmodules
file.
Sync
If a submodule's remote URL changes in .gitmodules
, e.g. because the repository is moved or forked, local checkouts need to be synchronised with the new remote address with git submodule sync
.
Update
git submodule update
does the equivalent of a git pull
in the submodule, only without using a branch.
Remove
We can remove the local checkout of a submodule like so:
git submodule deinit vendor/some-lib
Permanent deletion requires deletion of the link, which must be staged and commited:
git rm vendor/some-lib
For each
We can execute a command for each submodule:
git submodule foreach 'cat .gitmodules'