Empty Git submodule folder when repo cloned
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
An empty submodule directory after cloning is normal Git behavior when the submodule was not initialized and checked out yet. A submodule is recorded in the parent repository as a commit reference plus metadata, not as ordinary file content embedded in the parent tree. That is why the folder can exist while the actual nested repository content is still missing.
Clone with Submodules from the Start
The cleanest fix is to clone the repository with recursive submodule checkout enabled.
This tells Git to clone the parent repository, read .gitmodules, fetch the nested repositories, and check out the exact commits pinned by the parent.
If you skip this flag, the submodule path may be present but empty or uninitialized until you fetch it explicitly.
Initialize an Existing Clone
If you already cloned the parent repository, you do not need to start over. Initialize and update the submodules in place.
--init creates the submodule working trees locally. --recursive repeats the process for nested submodules inside those submodules.
This is the command most people need after discovering an empty directory in an already-cloned repository.
Understand What the Parent Repository Stores
A parent repository does not copy submodule files into its own Git objects the way it stores ordinary tracked files. Instead, it stores a gitlink entry that points to one specific commit in another repository.
That design is why the parent can track an exact dependency revision while keeping histories separate. It is also why cloning the parent alone is not enough to populate the submodule working tree.
Check .gitmodules and Access Rights
If git submodule update --init --recursive fails, the next place to look is .gitmodules and your repository access.
A common failure mode is that the parent repository is public but one or more submodules are private. In that case, the clone succeeds for the parent and the submodule path is created, but fetching the nested repository fails because your credentials do not allow it.
Another problem is a stale or broken submodule URL. If the recorded URL is wrong, Git cannot populate the folder even though the submodule entry exists.
Know What Detached HEAD Means in Submodules
After initialization, a submodule is often checked out at a detached HEAD. That is normal because the parent repository pins an exact commit, not necessarily a branch tip.
Do not assume detached HEAD means the checkout failed. It often means Git did exactly what the parent repository asked for.
Keep Submodule Commands Separate from Parent Commands
Submodules have their own working tree, history, and branch state. Updating the parent repository does not automatically mean the submodule content moves to a new commit unless the parent now points to one.
That separation is powerful, but it also causes confusion. Empty directories, detached checkouts, and unexpected revisions all make more sense once you remember that a submodule is a nested repository, not just a folder.
Common Pitfalls
- Cloning without
--recurse-submodulesand assuming submodules will populate automatically. - Forgetting to run
git submodule update --init --recursiveon an existing clone. - Mistaking a private or inaccessible submodule for a generic Git bug.
- Treating a detached
HEADin the submodule as a failure. - Assuming the parent repository stores submodule files the same way it stores normal tracked files.
Summary
- Empty submodule folders usually mean the submodule was not initialized yet.
- Use
git clone --recurse-submodulesfor a complete first clone. - Use
git submodule update --init --recursiveto populate an existing clone. - Check
.gitmodulesand credentials if initialization fails. - Remember that submodules are separate repositories pinned to specific commits.

