Git By Example
Git By Example

Submodules

2 min read

Chapter 17 — Submodules

Submodules let you include one Git repository inside another, pinned to a specific commit.

When to Use Submodules

Common use cases: shared libraries, vendor dependencies, monorepo-like setups where components have independent release cycles.

Adding a Submodule

Example: Add a submodule

git submodule add https://github.com/example/shared-lib.git libs/shared
Cloning into '/home/you/project/libs/shared'...
done.
git status
Changes to be committed:
        new file:   .gitmodules
        new file:   libs/shared

Example: See the .gitmodules file

cat .gitmodules
[submodule "libs/shared"]
    path = libs/shared
    url = https://github.com/example/shared-lib.git
git commit -m "Add shared-lib submodule"

🧠 What happened? Git recorded the submodule's URL and the exact commit it points to. The parent repo doesn't store the submodule's files — it stores a pointer.

Cloning a Repo with Submodules

Example: Clone and initialize submodules

git clone --recurse-submodules https://github.com/boringcollege/project.git

Or if you already cloned:

git submodule init
git submodule update

Or in one command:

git submodule update --init --recursive

Updating a Submodule

Example: Pull latest changes in a submodule

cd libs/shared
git fetch
git checkout v2.0.0
cd ../..
git add libs/shared
git commit -m "Update shared-lib to v2.0.0"

Example: Update all submodules to their latest remote commit

git submodule update --remote

🧠 What happened? Each submodule is an independent repo. You update it like any repo, then commit the new pointer in the parent.

Checking Submodule Status

Example: See which commit each submodule is on

git submodule status
 a1b2c3d4e5f6 libs/shared (v2.0.0)

Removing a Submodule

There's no single command. Here are the steps:

# 1. Remove from .gitmodules
git config -f .gitmodules --remove-section submodule.libs/shared

# 2. Remove from .git/config
git config --remove-section submodule.libs/shared

# 3. Remove the tracked directory
git rm --cached libs/shared

# 4. Remove the submodule directory
rm -rf libs/shared

# 5. Remove the submodule's .git data
rm -rf .git/modules/libs/shared

# 6. Commit
git commit -m "Remove shared-lib submodule"

Common Pitfalls

Detached HEAD: Submodules are always checked out in detached HEAD state. If you want to make changes, create a branch first:

cd libs/shared
git switch -c my-changes

Forgetting to push submodule changes: If you commit a new submodule pointer in the parent but forget to push the submodule's commits, collaborators will get errors. Always push the submodule first, then the parent.

cd libs/shared
git push
cd ../..
git push

← Chapter 16: Worktrees · Next: Chapter 18 — Branching Strategies →

Git By Example

A practical guide to Git — learn by doing, not by reading manuals.

View book →