Changing an existing submodule's branch
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Changing a Git submodule's branch is usually less direct than changing a normal repository branch. That is because a submodule does not really track a branch in the superproject. The superproject records a specific commit for the submodule, and optional branch configuration only affects how git submodule update --remote chooses future commits.
Start With the Right Mental Model
A submodule entry in the parent repository points to one commit in another repository. That means teammates who clone the parent project get the exact submodule commit recorded in the superproject, not automatically whatever is currently at main, develop, or some other branch.
So when people say they want to "change the submodule branch," there are usually two distinct operations:
- check out a different branch inside the submodule now
- configure which branch future remote updates should follow
Those are related, but not the same.
Switch the Working Copy Inside the Submodule
First move into the submodule and check out the branch you want.
At this point the submodule working tree is on develop. However, the parent repository still only knows about the specific commit now checked out there.
You can confirm this from the parent repository.
The parent repo will show the submodule as modified because its recorded commit changed.
Configure the Branch in .gitmodules
If you want git submodule update --remote to follow a different branch in the future, update .gitmodules.
You can also edit the file directly.
After editing .gitmodules, synchronize that configuration into local Git config.
This step keeps the local configuration aligned with what the repository now declares.
Record the New Submodule Commit in the Parent Repo
The parent repository must commit both changes:
- the
.gitmodulesupdate, if you changed branch tracking - the new submodule commit pointer
That commit is what teammates will pull. Without it, your local branch switch stays local and the parent repo does not actually record anything useful.
Use git submodule update --remote Correctly
Once the branch is configured, you can later update the submodule from the parent repo with:
Git will fetch the configured branch, move the submodule to the latest commit from that branch, and leave the parent repo ready to record the new submodule pointer.
This does not make the parent repo dynamically follow the branch on every clone. It still updates to a concrete commit that must be committed in the superproject.
Detached HEAD Is Normal in Submodules
A common surprise is seeing the submodule in a detached HEAD state after clone or update. That is normal because the parent project is checking out a specific commit.
If you want to do active development inside the submodule, explicitly check out a branch there. Detached HEAD is not an error by itself.
Be Careful With Team Workflows
Changing a submodule branch can affect builds, CI, deployment, and local developer expectations. If a project previously followed stable releases and you switch it to develop, that is a meaningful dependency policy change.
Make sure the branch you choose is intentional, and verify CI after the parent repo records the new submodule commit.
Common Pitfalls
- Thinking the parent repository stores a branch name instead of a submodule commit.
- Checking out the new branch inside the submodule but forgetting to commit the submodule pointer in the parent repo.
- Editing
.gitmoduleswithout runninggit submodule sync. - Assuming
git submodule update --remotechanges clones automatically without a parent commit. - Treating detached
HEADin a submodule as a bug when it is often expected behavior.
Summary
- A submodule is recorded in the parent repository as a specific commit.
- To change branches, first check out the desired branch inside the submodule.
- To make remote updates follow that branch, set the
branchfield in.gitmodules. - Commit both
.gitmodulesand the submodule pointer in the parent repository. - Detached
HEADin submodules is normal unless you are actively developing inside the submodule.

