Workflows
Submodule Update Flow
Outline a safe routine for updating submodules, locking revisions, and syncing the parent repository.
- Teams turning commands into repeatable routines
- Readers who need sequencing, branch, and sync discipline
- Basic understanding of fetch, pull, push, and branches
- A sense of how and why branches diverge
- Copying a workflow without checking branch state
- Choosing the wrong integration path on shared branches
A submodule update often looks like “changing a directory,” but that is misleading. You are really handling two repositories at once:
- the submodule repository itself
- the parent repository that records which submodule commit should be used
If those two layers are not kept separate in your head, submodule work quickly becomes confusing.
Why this workflow is easy to misread
A submodule is not just a normal folder. It is closer to “a repository state referenced by another repository.” That means every update has two separate questions:
- where does the submodule repository point now
- which submodule commit should the parent repository record as the shared baseline
Ignoring either layer creates confusing results later.
Suggested sequence
1. Move the submodule to the intended commit
git submodule update --init --recursive
cd path/to/submodule
git fetch origin
git switch main
git pull --ff-only
This step is about making sure the child repository itself is at the intended state.
2. Commit the pointer update in the parent repo
cd ../..
git status
git add path/to/submodule
git commit -m "chore: update submodule pointer"
The parent repository is not committing the child repository’s contents. It is committing which child commit should be used.
3. Verify init and recursive update behavior
git submodule update --init --recursive
This is the sanity check that tells you another developer can clone or update the parent repository and still land on the same child revision you intended.
A fuller example
git submodule update --init --recursive
cd path/to/submodule
git fetch origin
git switch main
git pull --ff-only
cd ../..
git status
git diff --submodule
git add path/to/submodule
git commit -m "chore: update submodule pointer"
The key value of this flow is separation: first update the child repository, then deliberately record the parent pointer.
Checks worth keeping every time
At minimum, confirm:
- the submodule repository really reached the target commit
- the parent repository shows only the expected submodule pointer change
git diff --submoduletells a story you can explain- recursive update commands still reproduce the intended state
When submodule workflows become especially risky
- the child repository is still on unstable branch work
- the team does not use a consistent recursive initialization routine
- nested submodules exist but people forget
--recursive - access or branch policy differs sharply between parent and child repositories
These are the moments when submodules stop feeling like dependency management and start becoming coordination debt.
The visible directory contents are only the surface. What the parent repository truly records is a commit pointer. If you look only at files and not at the referenced child commit, you may think you changed one thing while actually shipping another.
Common mistakes
Assuming the parent repository stores the submodule’s full file history
Usually it does not. It stores the child commit reference.
Updating the submodule but forgetting to commit the pointer change
Then teammates cannot reproduce the intended child version from the parent repository alone.
Forgetting initialization and treating the state as broken
Many “submodule is empty or weird” moments are just missing initialization.
Assuming submodule pointer changes do not need review
They do. A pointer change is a dependency baseline change and should be reviewed as such.
- Is the child repository already on a stable commit?
- Does the update bring API, config, or runtime implications?
- Should the parent repository end with exactly one expected submodule pointer change?
- Can another developer reproduce the same state with recursive update commands?
Good follow-up reads
Release branch workflowFeature branch collaborationSync before review