Stay ahead of the curve!
Subscribe to Learning Ocean to get coupons, early blog/course access, and exclusive videos.
Watch the full walkthrough on My YouTube Channel.
Video link for this topic: <VIDEO_URL>

Git Submodule — Reuse Common Code Across Projects

Imagine you’re working on a microservices project where multiple services need the same code—like a logging module or shared Git hooks.
Instead of duplicating code, Git gives us submodules: a way to embed one repository inside another while keeping its history separate.


What is a Git submodule?

A submodule is:

  • A Git repository inside another Git repository.
  • Always locked to a specific commit of the child repo.
  • Perfect for shared modules like logging, utilities, or custom hooks.

Think of it as a “read-only snapshot” of another repository inside your project.



Adding a Submodule

Let’s create a simple setup:

# start a main repo
git init git-tutorial
cd git-tutorial
echo "base project" > first.txt
git add first.txt
git commit -m "first commit"

Suppose we already have a logger repository hosted on GitHub.

Add it as a submodule

git submodule add git@github.com:user/logger.git logger
  • The first logger is the folder name inside your project.

  • Git creates:

    • A logger/ directory pointing to a specific commit of the logger repo.
    • A .gitmodules file describing the submodule.

Check the files:

ls -a
# .git  .gitmodules  first.txt  logger/

The .gitmodules file looks like:

[submodule "logger"]
    path = logger
    url  = git@github.com:user/logger.git

This file is version-controlled so that teammates know where the submodule lives.


How does Git know which commit?

Inside .git (not versioned), Git stores the exact commit ID of the submodule. When you push, Git records that pointer so others can clone the same commit—not just the latest branch tip.

This is key for stability:

Even if the logger repo keeps evolving, your project remains fixed to the known-good commit until you intentionally update.


Commit and Push the Submodule Pointer

After adding the submodule, commit both .gitmodules and the submodule pointer:

git add .gitmodules logger
git commit -m "Add logger as submodule"
git push origin main

On GitHub, you’ll notice:

  • logger/ shows up, but when you click it, GitHub displays the linked repo at a specific commit, not a normal folder.

Adding More Submodules

Need another shared repo—say, a Git hooks repo?

git submodule add git@github.com:user/hooks.git hooks
git add .gitmodules hooks
git commit -m "Add hooks submodule"
git push origin main

Your .gitmodules now lists both:

[submodule "logger"]
    path = logger
    url  = git@github.com:user/logger.git
[submodule "hooks"]
    path = hooks
    url  = git@github.com:user/hooks.git

Visual Summary


  • Main repo controls when to update each submodule.
  • Each submodule retains its own history and branching.

Key Benefits

FeatureValue
IsolationEach module is its own Git repo
StabilityAlways points to a known commit
ReusabilityPerfect for shared code across microservices
FlexibilityUpdate or pin versions independently

Keep Learning 🚀

👉 Subscribe to Learning Ocean – Subscribers get coupon codes for my courses, early access to blogs and courses, and even exclusive YouTube videos.

👉 My YouTube Channel – More videos, more fun, and lots of learning!

👉 📺 Watch this topic in video form

Stay curious, keep coding, and let’s make learning fun together! 🎉