---
title: "How to Have Git Repositories Nested Inside Each Other (The Submodules Solution)"
slug: "git-submodules-nested-repositories-guide"
published: "2025-09-10"
updated: "2025-12-26"
tags:
  - "git submodules"
  - "nested repositories"
  - "monorepo management"
  - "git workflow"
  - "submodule update"
  - "git best practices"
  - "repository nesting"
  - "git monorepo"
  - "version control"
  - "shared code management"
llm-intent: "reference"
audience-level: "intermediate"
framework-versions:
  - "git@2.45"
status: "stable"
llm-purpose: "Learn how to use Git submodules to nest repositories properly. Includes setup, workflow, cloning, and updating submodules with practical examples."
llm-prereqs:
  - "Access to Git"
  - "Access to Command Line"
llm-outputs:
  - "Completed outcome: Learn how to use Git submodules to nest repositories properly. Includes setup, workflow, cloning, and updating submodules with practical examples."
---

**Summary Triples**
- (git submodule add, command, git submodule add <repo-url> <path> — clones child repo into path and registers it as a submodule)
- (.gitmodules, createdBy, git submodule add — stores submodule path and URL for the parent repository)
- (commit after adding submodule, include, .gitmodules and the submodule path (the parent repo records a commit reference to the submodule))
- (cloning a repo with submodules, recommended, git clone --recurse-submodules <repo> or git clone <repo> && git submodule update --init --recursive)
- (initializing/updating submodules in an existing clone, commands, git submodule init && git submodule update --recursive (or git submodule update --init --recursive))
- (update submodules to their remote branch tip, command, git submodule update --remote --merge (fetches and merges upstream changes into each submodule))
- (submodule detached HEAD, warning, Submodules are often checked out at a specific commit (detached HEAD) — switch to a branch inside the submodule with git -C <path> checkout <branch>)
- (track branch for submodule, configuration, git config -f .gitmodules submodule.<path>.branch <branch> then git submodule sync)
- (remove submodule, steps, git submodule deinit -f <path> && rm -rf .git/modules/<path> && git rm -f <path> && git commit -m 'Remove submodule')
- (nested repository problem, cause, Without submodules, the parent repo attempts to track nested repo files, causing conflicts and history mixing)
- (submodule history, fact, Each submodule remains an independent Git repository with its own history and refs)

### {GOAL}
Learn how to use Git submodules to nest repositories properly. Includes setup, workflow, cloning, and updating submodules with practical examples.

### {PREREQS}
- Access to Git
- Access to Command Line

### {STEPS}
1. Follow the detailed walkthrough in the article content below.

<!-- llm:goal="Learn how to use Git submodules to nest repositories properly. Includes setup, workflow, cloning, and updating submodules with practical examples." -->
<!-- llm:prereq="Access to Git" -->
<!-- llm:prereq="Access to Command Line" -->
<!-- llm:output="Completed outcome: Learn how to use Git submodules to nest repositories properly. Includes setup, workflow, cloning, and updating submodules with practical examples." -->

# How to Have Git Repositories Nested Inside Each Other (The Submodules Solution)
> Learn how to use Git submodules to nest repositories properly. Includes setup, workflow, cloning, and updating submodules with practical examples.
Matija Žiberna · 2025-09-10

I was working on a project where I needed to include another Git repository inside my main repository. Sounds simple, right? But when I tried to initialize a new Git repo inside an existing one, Git immediately complained. You can't just have "Git inside Git" without proper setup.

After wrestling with .gitignore workarounds that never quite worked, I discovered the clean solution: Git submodules. This is exactly what they're designed for, and once you understand the workflow, it's incredibly powerful.

## The Problem with Nested Git Repositories

When you try to create a Git repository inside another Git repository, you run into immediate issues. The parent repository wants to track everything in its directory tree, but the nested repository needs its own independent version control. Without proper setup, you get conflicts, ignored changes, and a mess of version control chaos.

The breakthrough insight is that Git submodules solve this elegantly by creating a proper parent-child relationship between repositories while keeping their histories completely separate.

## Setting Up Git Submodules

Let's say you have a main project and want to include another repository inside it. Here's the step-by-step process:

```bash
# In your main project directory
cd /path/to/your-main-project

# Add the submodule
git submodule add https://github.com/username/child-repo.git path/to/nested-folder

# This creates the submodule and clones the repository
git add .gitmodules path/to/nested-folder
git commit -m "Add child repository as submodule"
```

This command does several important things. It clones the child repository into your specified folder, creates a `.gitmodules` file that tracks the submodule configuration, and sets up the proper Git relationship between parent and child.

The `.gitmodules` file looks like this:

```ini
# File: .gitmodules
[submodule "path/to/nested-folder"]
    path = path/to/nested-folder
    url = https://github.com/username/child-repo.git
```

This configuration file tells Git how to handle the nested repository, including where it lives and where to fetch updates from.

## Working with Nested Repositories

Once your submodule is set up, you have two completely independent Git repositories sharing the same workspace. Here's how to work with them:

```bash
# Work on the child repository
cd path/to/nested-folder

# Make changes to files
echo "console.log('Hello from nested repo');" > index.js

# Commit changes to the child repository
git add .
git commit -m "Add new feature to nested repo"
git push origin main

# Go back to parent repository
cd ../..

# The parent repo sees the submodule has new commits
git status
# Shows: modified: path/to/nested-folder (new commits)

# Update parent to point to latest child commits
git add path/to/nested-folder
git commit -m "Update nested repo to latest version"
```

The key concept here is that the parent repository doesn't track the individual files in the child repository. Instead, it tracks which specific commit of the child repository it should point to. This gives you complete separation while maintaining a clear relationship.

## Cloning Projects with Submodules

When someone else wants to clone your project with its submodules, they need to use special commands:

```bash
# Option 1: Clone with submodules in one command
git clone --recurse-submodules https://github.com/username/main-project.git

# Option 2: Clone first, then initialize submodules
git clone https://github.com/username/main-project.git
cd main-project
git submodule update --init --recursive
```

Without these commands, the submodule folder would exist but be empty. The `--recurse-submodules` flag tells Git to also clone all nested repositories and check out the correct commits.

## Updating Submodules

As the child repository evolves, you'll want to update your main project to use newer versions:

```bash
# Update submodule to latest remote version
git submodule update --remote path/to/nested-folder

# Or update all submodules at once
git submodule update --remote

# Commit the update to parent repository
git add .
git commit -m "Update submodules to latest versions"
```

This workflow lets you control exactly which version of the child repository your main project uses, giving you stability and control over dependencies.

## Why This Works So Well

Git submodules solve the "Git inside Git" problem by creating a proper parent-child relationship rather than trying to merge two repositories into one. The parent repository tracks a specific commit hash from the child repository, not the files themselves. This means both repositories maintain completely independent histories while sharing the same workspace.

You get the benefits of having everything in one place for development, while maintaining clean separation for version control. No .gitignore hacks, no workarounds - just proper Git architecture.

By following this approach, you can have as many nested repositories as you need, each maintaining its own independent development cycle while being easily accessible from your main project workspace.

Let me know in the comments if you have questions about setting up submodules, and subscribe for more practical Git guides.

Thanks, Matija

## LLM Response Snippet
```json
{
  "goal": "Learn how to use Git submodules to nest repositories properly. Includes setup, workflow, cloning, and updating submodules with practical examples.",
  "responses": [
    {
      "question": "How do I add a repository as a submodule?",
      "answer": "Steps: 1) cd into the parent repo root. 2) Run: git submodule add <repo-url> <path/to/submodule>. 3) git add .gitmodules <path/to/submodule>. 4) git commit -m \"Add submodule <name>\". Result: .gitmodules created and the parent records a commit pointer to the submodule."
    },
    {
      "question": "How do I clone a repository that contains submodules?",
      "answer": "Option A (one-step): git clone --recurse-submodules <parent-repo-url>. Option B (if already cloned): git submodule update --init --recursive. Both ensure submodule repos are cloned and checked out to the recorded commits."
    },
    {
      "question": "How do I update submodules to the latest remote changes?",
      "answer": "If you want to fetch and fast-forward each submodule to its remote-tracking branch: git submodule update --remote --merge. Alternatively, to update a single submodule: cd <path>; git fetch; git checkout <branch>; git pull — then in the parent repo: git add <path>; git commit -m \"Update submodule\"."
    },
    {
      "question": "Why is a submodule in a detached HEAD and how do I fix it?",
      "answer": "Submodules are recorded at a specific commit, so when checked out they often land in detached HEAD. Fix: cd <submodule-path>; git checkout <branch> (or create a branch: git checkout -b work/<name>); optionally set branch tracking in .gitmodules: git config -f .gitmodules submodule.<path>.branch <branch> and run git submodule sync."
    },
    {
      "question": "How do I remove a submodule cleanly?",
      "answer": "Steps: 1) git submodule deinit -f <path>. 2) rm -rf .git/modules/<path>. 3) git rm -f <path>. 4) Remove any leftover entry in .gitmodules if present and git add .gitmodules. 5) git commit -m \"Remove submodule <path>\". This removes the submodule registration and files from the parent."
    },
    {
      "question": "How do I contribute changes to a submodule and record them in the parent repo?",
      "answer": "Steps: 1) cd <submodule-path>. 2) Create a branch: git checkout -b feature/xyz. 3) Make changes, git add, git commit; git push origin feature/xyz. 4) In the parent repo: git add <submodule-path> (the commit pointer changed). 5) git commit -m \"Update submodule to include feature/xyz\" and push the parent repo."
    },
    {
      "question": "How do I make CI clone submodules?",
      "answer": "Common options: - Use git clone --recurse-submodules <repo> in your CI job. - If CI provides a shallow clone flag, combine with submodule init/update: git submodule update --init --recursive. - Ensure CI runner has access to submodule remotes (SSH keys or CI token) and that authentication is configured."
    },
    {
      "question": "How can I make a submodule follow a branch automatically?",
      "answer": "Set the desired branch in .gitmodules: git config -f .gitmodules submodule.<path>.branch <branch>; then git submodule sync && git submodule update --init --remote. Note: the parent still records a specific commit; updating to the branch tip requires running git submodule update --remote and committing the new submodule pointer in the parent."
    }
  ]
}
```