Git Submodules: Sharing and Versioning Code Across Multiple Git Repositories

Published by Charles DOUANGDARA
Category : DevOps
24/04/2026

Git Submodules are a Git feature that allows you to embed a Git repository inside another repository. This approach is particularly useful when multiple projects need to share a common library while maintaining precise control over the versions being used.

In this article, we will explore what a Git Submodule is, how it works, as well as its advantages and limitations in a software project.

 

 

A common problem: sharing and versioning code across multiple repositories

 

In many software projects, several applications or services share part of their code. This can include:

  • an internal library
  • common tools
  • reusable components

 

For example, a team may maintain multiple microservices that rely on the same internal library. This library may handle authentication, communicate with an external API, or implement certain business features.

Managing this shared code quickly becomes complex.

A first approach is to copy the code into each repository. This solution seems simple at first, but it quickly leads to issues:

  • updates must be applied manually
  • the risk of inconsistencies increases
  • it becomes difficult to track which versions are being used

 

Another approach is to place this code in a separate Git repository to version it independently.

However, a question quickly arises:

How can this external repository be integrated into multiple projects while controlling the version being used?

Git Submodules provide a solution to this problem. They allow a Git repository to be embedded into another repository while preserving its history and versioning.

Example of a structure with shared code:

 

 

Each service uses a shared library maintained in a separate repository.

With Git Submodules, a project may look like this:

 

 

The shared-library folder then corresponds to an external Git repository integrated into the project.

 

Git Submodules: overview

 

Definition and how it works

Git Submodules allow you to embed a Git repository within another repository while keeping them independent (see documentation).

The embedded repository has:

  • its own history
  • its own commits
  • its own lifecycle

 

When adding a submodule, Git does not simply copy files. The main repository stores a reference to a specific commit of the external repository.

This means that the parent project points to an exact version of the submodule.

All developers therefore use the same version of the shared code.

Git stores submodule information in the following file .gitmodules .

This file contains:

  • the remote repository URL
  • the path of the submodule within the project

 

Why Git Submodules solve this type of problem

Git Submodules allow a shared library or component to be maintained in a dedicated repository.

Projects that depend on it can then integrate this repository as a submodule.

Each project can choose which version of the component to use by pointing to a specific commit.

This approach provides several benefits:

  • project stability
  • precise version control
  • better traceability

 

Git records both:

  • the state of the main repository
  • the exact version of the submodule

 

It is therefore possible to reproduce the exact state of a project at a given point in time.

 

Main Git Submodules commands

 

Here are the most commonly used commands when working with Git Submodules.

 

Add a submodule

git submodule add https://github.com/organisation/shared-library.git libs/shared-library

This command:

  • adds the external repository
  • creates the .gitmodules file
  • stores the reference in the main repository

 

Clone a project with its submodules

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

This command retrieves:

  • the main repository
  • all submodules

 

Initialize submodules after cloning (if the project has already been cloned)

git submodule update --init --recursive

This command downloads all required submodules.

 

Advantages and disadvantages

 

Git Submodules offer several advantages for managing shared code:

  • Clear separation of repositories: A shared component can be developed in its own repository. Dependent projects can then integrate it as a submodule.
  • Precise version control: The main repository references a specific commit of the submodule. All developers therefore use exactly the same version.
  • Code reuse: Submodules avoid code duplication. Fixes or improvements can be made directly in the shared repository.
  • Independent Git history: Each component keeps its own Git history. This makes tracking changes and maintenance easier.

 

However, despite these advantages, Git Submodules also introduce certain constraints:

  • Workflow complexity: Developers must understand submodule initialization/update and synchronization with the main repository
  • Less intuitive workflow: When a submodule changes, the submodule repository must be updated and the reference in the main repository must also be updated. This extra step can lead to errors.
  • More complex CI/CD management: A simple git clone does not automatically retrieve submodules. Additional commands must be used in pipelines.

 

Alternatives to Git Submodules

 

Git Submodules are not the only solution for sharing code.

 

Monorepo

https://monorepo.tools/

In a monorepo, multiple projects are grouped within a single repository.

 

Advantages:

  • simplified dependency management
  • easier multi-project changes

 

Disadvantage:

  • potentially very large repository

 

Git Subtree

https://docs.github.com/en/get-started/using-git/about-git-subtree-merges

Git Subtree allows you to directly integrate the content of one repository into another.

 

Advantage:

  • simpler workflow for developers

 

Disadvantage:

  • less clear history management

 

Package managers

Another approach is to publish a library as a package.

 

Examples:

  • NuGet for .NET
  • npm for JavaScript

 

Projects can then consume this library as a standard dependency.