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.