Git Notes
Learn how to use Git submodules to include external repositories within your project. Cover adding, updating, cloning with submodules, and alternatives.
Git submodules allow you to keep a Git repository as a subdirectory of another Git repository. This is useful for including external libraries, shared components, or any project that has its own development lifecycle.
What Are Submodules?
A submodule is a reference to a specific commit in another repository. Your main repo stores:
- The URL of the submodule repository
- The specific commit SHA to use
- The path where it should be checked out
Adding a Submodule
git submodule add https://github.com/org/shared-lib.git libs/shared-libCloning into 'libs/shared-lib'... remote: Enumerating objects: 145, done. remote: Total 145 (delta 0), reused 0 (delta 0) Receiving objects: 100% (145/145), done.
This creates/modifies two files:
cat .gitmodules[submodule "libs/shared-lib"]
path = libs/shared-lib
url = https://github.com/org/shared-lib.git# The submodule reference is staged
git statusOn branch main
Changes to be committed:
new file: .gitmodules
new file: libs/shared-lib# Commit the submodule addition
git commit -m "Add shared-lib submodule"Cloning a Project with Submodules
Method 1: Clone Then Initialize
git clone https://github.com/org/my-project.git
cd my-project
# Submodule directories exist but are empty
git submodule init
git submodule updateMethod 2: Clone with --recurse-submodules
git clone --recurse-submodules https://github.com/org/my-project.gitThis automatically initializes and clones all submodules.
Updating Submodules
Update to the Commit Referenced by Parent
git submodule updateUpdate to Latest Remote Commit
# Update all submodules to latest
git submodule update --remote
# Update a specific submodule
git submodule update --remote libs/shared-libSubmodule path 'libs/shared-lib': checked out 'abc1234def567890...'
# After updating, commit the new reference
git add libs/shared-lib
git commit -m "Update shared-lib to latest version"Pull Changes in Submodule Directly
cd libs/shared-lib
git pull origin main
cd ../..
git add libs/shared-lib
git commit -m "Update shared-lib submodule"Working Inside Submodules
# Navigate into submodule
cd libs/shared-lib
# It is a regular Git repo
git log --oneline -5
git branch -a
# Make changes and commit
echo "new feature" >> feature.js
git add . && git commit -m "Add feature"
git push origin main
# Go back to parent and update reference
cd ../..
git add libs/shared-lib
git commit -m "Update shared-lib to include new feature"Removing a Submodule
# 1. Remove from .gitmodules
git submodule deinit -f libs/shared-lib
# 2. Remove from .git/modules
rm -rf .git/modules/libs/shared-lib
# 3. Remove the working directory
git rm -f libs/shared-lib
# 4. Commit
git commit -m "Remove shared-lib submodule"Submodule Status
git submodule statusabc1234def567890 libs/shared-lib (v2.1.0) +def5678abc901234 vendor/ui-framework (v1.3.0-5-gabc1234) -ghi9012def345678 libs/analytics
Prefix meanings:
(space): Checked out at the correct commit+: Checked out at a different commit than recorded-: Not initialized
Foreach Command
Run a command in each submodule:
# Pull latest in all submodules
git submodule foreach git pull origin main
# Check status of all submodules
git submodule foreach git status
# Run custom commands
git submodule foreach 'echo $name: $path ($sha1)'Submodules vs Subtrees
| Feature | Submodules | Subtrees |
|---|---|---|
| External repo reference | ✅ SHA pointer | Merged into tree |
| Clone complexity | Higher (--recurse) | None (included) |
| Contributor experience | Must know submodules | Transparent |
| Independent history | ✅ Separate | Merged into parent |
| Push back changes | ✅ Easy | Possible but complex |
| Disk space | Efficient (on demand) | Always included |
Common Issues and Solutions
Submodule Directory is Empty After Clone
git submodule init
git submodule updateDetached HEAD in Submodule
Submodules check out specific commits, not branches:
cd libs/shared-lib
git checkout main # Switch to a branch if neededModified Submodule Showing in Parent Status
Interview Questions
- What is a Git submodule?
A submodule is a Git repository embedded inside another repository at a specific commit. The parent repo stores a reference (URL + commit SHA) to the submodule, allowing you to include external code with its own version history.
- How do you clone a repository that contains submodules?
Use git clone --recurse-submodules <url> to clone and initialize submodules in one step. Alternatively, clone normally then run git submodule init and git submodule update.
- Why do submodules often end up in a detached HEAD state?
Because the parent repository points to a specific commit SHA, not a branch. When you update a submodule, Git checks out that exact commit, resulting in a detached HEAD.
- When would you use submodules vs a package manager?
Use submodules when you need to develop and modify the dependency alongside your project, or when it is not available through a package manager. Use package managers for stable, versioned libraries you consume but do not modify.
- How do you update a submodule to point to a newer commit?
Run git submodule update --remote to fetch the latest commit, then git add <submodule-path> and commit in the parent repo to record the new reference.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Git Submodules - Manage External Dependencies as Git Repos.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Git & GitHub topic.
Search Terms
git-github, git & github, git, github, advanced, submodules, git submodules - manage external dependencies as git repos
Related Git & GitHub Topics