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](/git/faqs/clone-repository-with-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:

```bash
git pull --recurse-submodules
```

Or, after a normal pull:

```bash
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](/git/commands/git-pull).

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:

```bash
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`:

```bash
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:

```bash
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`:

```bash
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](/git/faqs/what-is-git-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](https://www.deployhq.com/blog/using-submodules-in-deploy) 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](/git/commands/git-submodule). To drop a submodule you no longer need, see [how to remove a submodule](/git/faqs/remove-a-git-submodule).

Deploying a project with submodules? [DeployHQ](https://www.deployhq.com/features/automatic-deployments) can deploy it every time you push.
