Skip to content
LatchkeyLatchkey home

git submodule: Usage, Options & Common CI Errors

git submodule embeds another repository at a fixed commit inside your repo.

Submodules are not fetched by a plain clone. CI must init and update them, often with private-repo auth.

What it does

git submodule tracks external repositories as nested checkouts pinned to a specific commit, recorded in .gitmodules and the parent tree.

Common usage

Terminal
git submodule update --init --recursive
git submodule sync --recursive        # apply URL changes
git submodule add https://github.com/owner/lib.git libs/lib
git submodule status
git clone --recurse-submodules <url>

Options

Subcommand / flagWhat it does
update --initInitialize and fetch submodules
--recursiveRecurse into nested submodules
syncUpdate submodule URLs from .gitmodules
--remoteUpdate to the latest upstream commit
add <url> <path>Add a new submodule

Common errors in CI

Empty submodule directories mean update --init was never run. fatal: could not read Username for a submodule means a private submodule needs credentials - provide a token or use insteadOf URL rewriting. In actions/checkout, set submodules: recursive and a token with access.

Using this in CI

CI checkouts are shallow and detached by default, which changes the answer this command gives you. Commands that read history, branch names, or tags need the checkout configured for it.

.github/workflows/ci.yml
- uses: actions/checkout@v4
  with:
    fetch-depth: 0   # history, tags, and git describe all need this

- run: |
    git rev-parse --is-shallow-repository   # expect false
    git rev-parse --abbrev-ref HEAD          # prints HEAD when detached

Frequently asked questions

git submodule: Usage, Options & Common CI Errors?
Submodules are not fetched by a plain clone. CI must init and update them, often with private-repo auth.
What it does?
git submodule tracks external repositories as nested checkouts pinned to a specific commit, recorded in .gitmodules and the parent tree.
Common errors in CI?
Empty submodule directories mean update --init was never run. fatal: could not read Username for a submodule means a private submodule needs credentials - provide a token or use insteadOf URL rewriting. In actions/checkout, set submodules: recursive and a token with access.

Related guides

References

Run this faster and cheaper on Latchkey managed runners - self-healing included. Start free → 30-day trial · No credit card