Why and how to use Git submodules
Posted on April 22, 2025 • 6 min read • 1,205 wordsGit submodules let you manage dependencies across repositories cleanly and efficiently. Learn how and when to use them effectively in infrastructure projects.

Git submodules are a built-in feature that lets you include one Git repository inside another. This approach is useful when you need to manage dependencies between different codebases while keeping them autonomous.
Submodules point to a specific commit of an external repository. This ensures that every version of the main project uses exactly the same revision of its submodules, providing consistency and reproducibility.
Submodules help you compose a project from multiple repositories, each evolving independently but tracked together in a unified, coherent state.
When working on complex projects, you often need to include other Git projects as dependencies. Git provides a feature called submodules that lets you embed one repository inside another. This is especially useful for shared libraries, reusable components, or any external code.
To add a submodule to your project, run:
git submodule add <repository-url> <path/in/your/project>For example:
git submodule add https://github.com/my-user/my-library.git libs/my-libraryThis command will:
libs/my-library..gitmodules file describing the submodule.Don’t forget to commit these changes:
git commit -am "Add my-library submodule"When cloning a project that contains submodules, you must initialize and fetch them separately:
git clone <project-url>
git submodule init
git submodule updateOr more simply:
git clone --recurse-submodules <project-url>To update a submodule to the latest version on its main branch (e.g., main), do:
cd <path/to/submodule>
git checkout main
git pull
cd ../
git add <path/to/submodule>
git commit -m "Update submodule"Important: always commit in the parent project after modifying a submodule, because it tracks a specific SHA-1, not a branch.
To remove a submodule, you need to:
.gitmodules..git/config.Commands:
git submodule deinit -f <path/to/submodule>
rm -rf .git/modules/<path/to/submodule>
git rm -f <path/to/submodule>
git commit -m "Remove submodule"Git submodules are a powerful tool for managing dependencies in your projects. They allow you to maintain precise control over the versions in use and facilitate modular code organization. However, they require disciplined management to avoid conflicts and synchronization issues.
Feel free to use them whenever you need to include external projects while keeping your codebase clean and clearly organized.
Knowing the right use cases helps you avoid unnecessary complexity.
| Use Case | Why Submodules Are Suitable |
|---|---|
| Shared libraries across multiple projects | Locks each project to a specific version |
| Infrastructure components (e.g., Terraform, CDK) | Enables reuse with strict version control |
| External plugins in dedicated repos | Enforces tight integration with main code |
| Projects with distinct release cycles | Isolates updates and maintains independence |
Summary: Submodules excel when you need strict integration of independently maintained components without sacrificing version control precision.
git submodule update --init --recursive after cloning.README.md.--depth=1).git submodule foreach git pull origin mainUpdates all submodules in one command.
.gitmodules| Feature | Submodule | Subtree | Package Manager |
|---|---|---|---|
| Separate Git history | ✅ | ✅ | ❌ |
| Track specific commits | ✅ | ✅ | ❌ |
| Ease of configuration | ❌ | ✅ | ✅ |
| Suited for infrastructure code | ✅ | ✅ | ❌ |
Using:
git clone <repo>Symptoms : Submodule folders appear empty or incomplete
Solution :
Clone with:
git clone --recurse-submodulesOr afterward:
git submodule update --init --recursiveDevelopers often run ‘git pull’inside a submodule but forget to commit the updated SHA in the parent project.
Symptoms:
Solution : After update :
git add path/to/submodule
git commit -m "Update submodule"Git does not point to a branch but to a specific commit → you must commit the update."
By default, submodules checkout a detached HEAD.
Symptoms
Solution : Always checkout
git checkout mainDevelopers often edit a submodule thinking they are editing the parent project.
Symptoms:
Best practice:
.gitmodules and .git/config
Renaming submodule paths or changing URLs can desynchronize configuration files.
Symptoms:
Solution: Always update both files:
git mv old/path new/path
git add .gitmodules new/path
git commit -m "Fix submodule path"Very common: pipelines don’t load submodules.
Symptoms:
Solution :
In GitHub Actions (example) :
- name: Checkout repository
uses: actions/checkout@v4
with:
submodules: recursiveOr universally:
git submodule update --init --recursiveMistake:
Pointing the submodule to main or develop and expecting Git to auto-update it.
Git will never auto-update a submodule.
Symptoms:
Solution:
Always point to a tag or a fixed commit.
This is the very principle behind how submodules work."
Manually deleting the submodule folder corrupts internal Git metadata.
Symptoms:
Safe removal procedure:
git submodule deinit -f path/to/module
rm -rf .git/modules/path/to/module
git rm -f path/to/module
git commit -m "Remove submodule"Git submodules are a powerful tool when used with care. They fit modular architectures, DevOps environments, and projects requiring precise versioning.
Evaluate whether the complexity is justified. Used properly, submodules let you build a project from autonomous building blocks while maintaining clean version control.