--- topic: submodules source_keys: - git-scm-submodule-docs --- # Submodules — Deep Reference ## Update flag reference | Flag | Meaning | |---|---| | `--init` | Run init first (avoids a separate step) | | `--remote` | Use the submodule's remote branch tip instead of the superproject's recorded commit | | `--checkout` | Detached HEAD at recorded commit (default) | | `--rebase` | Rebase current branch onto recorded commit | | `--merge` | Merge recorded commit into current branch | | `--recursive` | Operate on nested submodules | | `--jobs ` | Parallel clone (defaults to `submodule.fetchJobs`) | | `-N` / `--no-fetch` | Skip remote fetch | | `--depth ` | Shallow clone | | `--filter ` | Partial clone filter | ## Workflow patterns ### Clone a repo with submodules ```bash git clone --recurse-submodules # Git 2.13+, one step # or git clone git submodule update --init --recursive ``` ### Add a dependency as a submodule ```bash git submodule add https://github.com/org/lib.git libs/lib git commit -m "chore: add lib as submodule" ``` ### Keep submodules pinned to the superproject's recorded commit ```bash git submodule update --recursive # after every git pull git config submodule.recurse true # do this automatically on pull ``` ### Update submodules to the latest commit on their tracked branch ```bash git submodule update --remote --merge --recursive git commit -am "chore: update submodules to latest" ``` ### Override a submodule URL locally (private mirror) ```bash git submodule init # edit .git/config: submodule..url = git submodule update ``` Local-only override (`.git/config`, not `.gitmodules`) — doesn't propagate to collaborators. Re-running `sync` overwrites it with the `.gitmodules` URL. ## Removal, in full `deinit` alone does not remove a submodule — it only clears `.git/config` and empties the working tree. To fully remove: ```bash git submodule deinit -f # unregister from .git/config git rm # remove .gitmodules entry + gitlink from index rm -rf .git/modules// # stale git dir; not tracked by git, not auto-cleaned git commit -m "chore: remove submodule" ``` `.git/modules//` persisting after `git rm` will block re-adding the same path until manually deleted. ## Relocate an embedded `.git` directory ```bash git submodule absorbgitdirs [...] ``` Moves a submodule's own `.git` directory into the superproject's `.git/modules//`, linking it back with a `.git` pointer file. Needed when a submodule was created or copied without going through `git submodule add` (e.g. converting a plain nested repo into a proper submodule). ## `foreach` shell variables Available inside the `` argument to `git submodule foreach`: | Variable | Meaning | |---|---| | `$name` | Logical submodule name | | `$sm_path` | Path relative to superproject root | | `$displaypath` | Path relative to current working directory | | `$sha1` | Recorded commit SHA | | `$toplevel` | Superproject's root path | ```bash git submodule foreach --recursive '' git submodule foreach 'git pull origin main || :' # || : continues past failures ```