Skip to main content
Advanced Git Commands
CHAPTER 12 Advanced

Submodules and Monorepos

Updated: May 15, 2026
20 min read

# CHAPTER 12

Submodules and Monorepos

1. Introduction

Modern software architecture rarely fits into a single, simple folder. You might be building a web application that relies on a proprietary UI library maintained by a completely different team. Alternatively, you might be a massive enterprise like Google or Facebook, choosing to store billions of lines of code for thousands of different projects within one single, gigantic repository. In this chapter, we will explore the two dominant architectural strategies for scaling Git: Git Submodules, which allow you to nest separate repositories inside each other like Russian nesting dolls, and Monorepos, the controversial strategy of putting everything into one massive bucket.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Define the operational concept of a Git Submodule.
  • Add, update, and clone a repository containing submodules.
  • Understand the "Detached HEAD" trap inherent to submodules.
  • Define Monorepo architecture and contrast it with Polyrepo architecture.
  • Understand the performance implications of massive Git repositories.

3. Beginner-to-Advanced Explanations

The Polyrepo Problem: You are building Website-A. It needs a special button. You build the button inside the Website-A repository. Next week, you build Website-B. It needs the exact same button. If you copy/paste the button code, you now have duplicated code. If you find a bug in the button, you have to manually fix it in both repositories.

The Submodule Solution: You create a completely separate repository called Shared-Buttons. You go into Website-A and type a command that links Shared-Buttons into a subfolder. You do the same in Website-B. Now, Website-A and Website-B both point to the exact same external code. If you fix the button in the central repository, both websites instantly get the update.

4. Submodules in Action

A submodule is technically just a reference. Git does not track the *files* inside the submodule folder; it tracks the *commit hash* of the external repository.
bash
1234567
# Add an external repository as a sub-folder in your current project
git submodule add https://github.com/example/shared-buttons.git vendor/buttons

# When you clone a project that has submodules, they are empty by default!
# You MUST run these two commands to download the internal code:
git submodule init
git submodule update

The Detached HEAD Trap: When you enter the vendor/buttons folder, you are inside a completely different Git repository. However, by default, Git checks out the exact hash required by the parent project, leaving the submodule in a "Detached HEAD" state. If you try to write code inside the submodule without creating a branch first, you will lose your work.

5. The Monorepo Alternative

Submodules are notoriously difficult to use, leading to frequent developer errors and synchronization nightmares across teams. Because of this, the industry swung in the exact opposite direction: The Monorepo.

In a Monorepo, you abandon the idea of separating Website-A, Website-B, and Shared-Buttons into different Git repositories. You create ONE massive Git repository called Company-Codebase and put everything inside it.

  • Pros: No submodules required. No complex cross-repository dependency management. If you update the Shared-Buttons API, you can instantly update every website that uses it in a single, massive commit. You have a unified version history across the entire company.
  • Cons: The repository becomes mathematically massive. Standard Git commands like git clone or git status will take 30 minutes to execute because they have to scan millions of files.

6. Mini Project: Create Project with Submodules

Let's link two repositories together.

Step-by-Step Walkthrough: *(You will need two local folders to simulate this)*

  1. 1. Create the library: mkdir my-library && cd my-library && git init
  1. 2. Add code: echo "Shared Library Code" > lib.txt && git add . && git commit -m "V1"
  1. 3. Step back: cd ..
  1. 4. Create the main app: mkdir main-app && cd main-app && git init
  1. 5. Add the Submodule: Note that we are linking a local file path, but normally this is a GitHub URL.
``bash git submodule add ../my-library shared-lib `
  1. 6. Run git status. You will see two new things to commit: the shared-lib folder, and a hidden .gitmodules file.
  1. 7. Open the .gitmodules file in a text editor. You will see the plain-text mapping connecting the URL to the local folder path.
  1. 8. Commit the connection: git commit -m "Add shared library submodule"

7. Managing Monorepo Performance

If your company chooses the Monorepo path, Git will eventually choke. Senior engineers must deploy advanced optimization commands:
  • Shallow Clones: Instead of downloading 10 years of company history, developers run git clone --depth 1 <url>. This only downloads the newest commit, saving gigabytes of bandwidth.
  • Sparse Checkout: If the monorepo contains 500 projects, but you only work on the "iOS App" team, you use git sparse-checkout to tell Git to *only* download the ios/ folder to your hard drive, ignoring the other 499 projects entirely.

8. Best Practices

  • Automate Submodule Updates: If your team relies on submodules, junior developers will constantly forget to run git submodule update after pulling, leading to confusing crashes. You must write a script (like a Makefile or an NPM hook) that automatically runs the update command for them whenever the project is built.

9. Common Mistakes

  • Committing Submodule Changes Unintentionally: If a developer goes into a submodule folder, runs git pull to update the library, and then goes back to the parent folder and types git commit -am "Update", they have permanently updated the reference hash for the entire team. If that new library version breaks the main app, they just broke the app for everyone. Submodule updates must be treated with extreme caution.

10. Exercises

  1. 1. What specific hidden configuration file is generated by Git to map submodule URLs to local directory paths?
  1. 2. Explain the operational difference and primary benefit of git sparse-checkout` within a massive enterprise Monorepo.

11. FAQs

Q: What is a Git Subtree? A: Git Subtree is an alternative to Submodules. It allows you to nest a repository, but unlike submodules (which just store a reference pointer), Subtree physically copies the actual code and history of the external repository directly into your parent project. It is easier for junior developers to use, but bloats the parent repository significantly.

12. Summary

In Chapter 12, we tackled the complexities of scaling version control across interdependent projects. We mastered the precise architecture of Git Submodules, allowing us to compose complex applications by securely linking external repositories without code duplication. Conversely, we explored the industry shift toward Monorepo architecture, acknowledging its advantages in unified dependency management while learning the advanced commands (like Sparse Checkout) required to mitigate its immense performance overhead.

13. Next Chapter Recommendation

Whether you use submodules or a monorepo, your code will eventually reach a point where it is ready to be delivered to customers. How do you officially stamp a specific commit as "Version 1.0"? Proceed to Chapter 13: Git Tags and Release Management.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·