How do I update (pull) Git submodules?
After a git pull, your submodule folders can still be sitting on old commits. That is expected: a submodule is pinned to one specific commit by the main repository, and git pull does not move it unless you ask. This page covers keeping submodules in sync on a repository you already have. If you are setting up a fresh copy, see how to clone a repository with its submodules.
Update submodules to the commit the main repository records
Use this when a teammate bumped a submodule and you want your checkout to match. From the root of the repository:
git pull --recurse-submodules
Or, after a normal pull:
git submodule update --init --recursive
Both check out the exact commit the main repository points to. --init registers submodules that were added since your last pull, and --recursive handles submodules inside submodules. For the pull side of this, see the git pull command reference.
To make git pull do this every time, run git config submodule.recurse true once.
Update submodules to the latest upstream commit
Use this when you want the submodule's newest code, not the commit the main repository currently records:
git submodule update --remote
This fetches each submodule's remote and checks out the latest commit of the tracked branch. To merge it into the submodule's current branch instead of checking it out, add --merge:
git submodule update --remote --merge
Nothing is shared yet. The main repository now sees the submodule at a new commit, and git status shows it as modified. Commit the new pointer so everyone else, and your deployments, get the same version:
git add path/to/submodule
git commit -m "Update submodule to latest"
git push
Which branch does --remote follow?
By default, --remote follows the remote's default branch (origin/HEAD) of the submodule. To track a specific branch, record it in .gitmodules:
git config -f .gitmodules submodule.path/to/submodule.branch main
(Replace path/to/submodule with the submodule's name as it appears in .gitmodules, and main with your branch.) Commit the .gitmodules change. You can also set the branch when adding a submodule with git submodule add -b <branch> <url>.
Why submodule updates "don't work"
| Symptom | Cause | Fix |
|---|---|---|
Submodule folder is on an old commit after git pull |
git pull does not update submodules by default |
Add --recurse-submodules, or run git submodule update --init --recursive |
| Submodule folder is empty | Submodule never initialised on this machine | git submodule update --init --recursive |
--remote pulled changes, but a teammate or the server still sees the old version |
The new pointer was not committed and pushed in the main repository | git add the submodule path, commit and push |
| Your commits inside the submodule disappear after an update | git submodule update checks out a commit in a detached HEAD; work there is not on a branch |
Run git checkout <branch> inside the submodule before committing, or recover with git reflog |
| Fetch fails after the submodule's URL changed | Your local config still has the old URL | git submodule sync --recursive, then update again |
To see where each submodule stands, run git submodule status. A leading - means the submodule is not initialised, + means the checked-out commit differs from the one the main repository records, and U means it has merge conflicts.
Updating submodules in a deployment
The main repository records one specific commit for each submodule, so a newer submodule version only reaches your servers once you commit and push the updated pointer. Running git submodule update --remote locally changes nothing on your servers until you do. If a private submodule fails with an authentication error or a missing URL during a deploy, the account or key used for the main repository also needs read access to the submodule. Our guide to submodule errors during deployment walks through the common failures.
Quick reference
| Goal | Command |
|---|---|
| Pull and update submodules to the recorded commits | git pull --recurse-submodules |
| Update submodules after a normal pull | git submodule update --init --recursive |
| Move submodules to the latest upstream commit | git submodule update --remote |
| Merge upstream into the submodule's branch | git submodule update --remote --merge |
| Recurse by default in this repository | git config submodule.recurse true |
| Fix a changed submodule URL | git submodule sync --recursive |
| See each submodule's state | git submodule status |
For the full list of options, see the git submodule command reference. To drop a submodule you no longer need, see how to remove a submodule.
Deploying a project with submodules? DeployHQ can deploy it every time you push.