Git
Submodules
Cloning
Repository
Troubleshooting

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.

bash
git clone --recurse-submodules https://example.com/project.git

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.

bash
git submodule update --init --recursive

--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.

bash
cat .gitmodules

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.

bash
cd path/to/submodule
git status

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-submodules and assuming submodules will populate automatically.
  • Forgetting to run git submodule update --init --recursive on an existing clone.
  • Mistaking a private or inaccessible submodule for a generic Git bug.
  • Treating a detached HEAD in 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-submodules for a complete first clone.
  • Use git submodule update --init --recursive to populate an existing clone.
  • Check .gitmodules and credentials if initialization fails.
  • Remember that submodules are separate repositories pinned to specific commits.

Course illustration
Course illustration

All Rights Reserved.