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.
git statusshould include the up to date status of submodules or not.
git pushto push new objects from submodules to their remotes.
.gitmodulescontains named submodules, with their in-tree paths and remote URLs. It's checked in and versioned alongside our code.
- Submodule content is stored in
- Submodules are linked from their configured
pathto their checkout in
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
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
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.
git submodule update does the equivalent of a
git pull in the submodule, only without using a branch.
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
We can execute a command for each submodule:
git submodule foreach 'cat .gitmodules'