Git Submodules Guide

Git submodules allow you to include one Git repository within another. They are useful for handling shared libraries, vendor code, or reusable components across different projects without copying files. Each submodule is tied to a specific commit of an external repository, keeping its history and setup distinct from the main project.

This tutorial covers how to add, clone, update, and manage Git submodules properly, including commands and strategies to avoid common mistakes.

The Short Answer Version

Add a submodule to your repository

$ git submodule add https://github.com/user/repo.git path/to/submodule

Initialize submodules in a cloned repository

Update submodules to fetch content

Clone repository and its submodules in one step

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

Pull latest commits from submodule’s remote

$ git submodule update --remote

Remove a submodule completely

$ git submodule deinit -f path/to/submodule
$ rm -rf path/to/submodule
$ git rm path/to/submodule
$ rm .gitmodules

Add a Git Submodule

Submodules enable you to connect another Git repository to your project while keeping its version history and configuration independent. This section demonstrates the steps for adding a submodule to an already initialized Git project.

Command Syntax

To include a submodule, use:

git submodule add <submodule-url> <path>

  • <submodule-url>: The remote Git repository’s URL to link.
  • <path>: The directory path inside your project where the submodule will be placed.

Git saves this reference in a .gitmodules file and treats the submodule as a pointer to a specific commit.

Command Demonstration

Create a project directory.

$ mkdir my-project && cd my-project

Initialize the directory as a Git repository.

Add a submodule.

$ git submodule add https://github.com/example/repo.git vendor/example-lib

This command clones the external repository into the vendor/example-lib folder and creates a .gitmodules file.

Check the .gitmodules file.

Output:

[submodule "vendor/example-lib"]
    path = vendor/example-lib
    url = https://github.com/example/repo.git

Stage the .gitmodules file and the submodule folder.

$ git add .gitmodules vendor/example-lib

Commit the addition of the submodule.

$ git commit -m "Add example-lib as submodule"

Push your committed changes to the remote repository.

Clone a Repository with a Git Submodule

When cloning a repository that contains submodules, Git will not automatically retrieve the submodule content unless specifically instructed. This section details how to properly initialize and update submodules.

Command Syntax

To initialize and update submodules manually after cloning:

git clone <repo-url>
cd <repo-name>
git submodule init
git submodule update

To clone the repository and submodules in a single step:

git clone --recurse-submodules <repo-url>

  • --recurse-submodules: Automatically clones and initializes all submodules during the initial clone.
  • git submodule init: Registers submodules defined in .gitmodules.
  • git submodule update: Downloads the contents of the submodules.

To refresh submodules to the most recent remote-tracked commits:

git submodule update --remote

  • --remote: Pulls the latest commit from the tracked branch of the submodule.

Command Demonstration

Clone the primary repository:

$ git clone https://github.com/example/project.git

Move into the repository folder:

Initialize the submodules defined in .gitmodules:

Fetch the submodule contents:

Alternative: Clone the repository and submodules in one step.

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

Optional: Update submodules to the most recent commit from the remote branch.

$ git submodule update --remote

By default, submodules point to a fixed commit. Use --remote only if you want to sync to the latest upstream commit from the tracked branch.

Precautions for Adding a Git Submodule

  • Submodules point to commits, not branches.
    By default, submodules are tied to a fixed commit. They do not follow the latest changes of the remote repository automatically. You must update them manually using git submodule update --remote.
  • Submodule updates must be committed.
    If you move a submodule to a different commit, the parent repository registers this as a change. You must stage and commit the updated pointer.
  • Cloning requires additional steps.
    Users must either run git submodule init and git submodule update or clone with --recurse-submodules.
  • Workflows become more complex.
    If branches reference different submodule commits, merges and rebases can be complicated. Ensure coordination when working in teams.
  • CI/CD pipelines require submodule handling.
    Automated build or deployment processes must include logic to fetch and update submodules. A common issue is forgetting to include --recurse-submodules.

Submodules should be used only when independent versioning of external repositories is truly required. Otherwise, solutions like package managers or monorepo structures may be simpler to maintain.

Remove a Git Submodule

If you no longer need a Git submodule, follow these steps to remove it completely:

Deinitialize the submodule:

$ git submodule deinit -f vendor/example-lib

Delete the submodule directory:

$ rm -rf vendor/example-lib

Remove the submodule entry from .gitmodules:

$ git config -f .gitmodules --remove-section submodule.vendor/example-lib

Stage the modified .gitmodules file:

Remove the submodule configuration from Git:

$ git config --remove-section submodule.vendor/example-lib

Remove the submodule from the Git index:

$ git rm --cached vendor/example-lib

Commit the cleanup:

$ git commit -m "Remove vendor/example-lib submodule"

Push the changes to the remote repository:

These steps ensure that all references to the submodule are completely removed from your Git project.

Conclusion

In this tutorial, you learned how to use Git submodules to organize reusable code across multiple projects. You added submodules to a repository, cloned projects with submodules, updated them to pull remote changes, and removed them when no longer necessary. By leveraging submodules correctly, you can keep project structures modular, avoid code duplication, and ensure consistency in versioning dependencies.

Source: vultr.com

Create a Free Account

Register now and get access to our Cloud Services.

Posts you might be interested in: