Imagine you’re developing a large project that requires several independent code libraries, such as a utility library maintained by a team or a third-party component. If you have to manually copy and paste code updates every time, it’s cumbersome and error-prone. That’s where Git Submodules come in handy!

What are Git Submodules?

In simple terms, a Git submodule is a separate Git repository (called a “submodule”) that is included as a subdirectory within another Git repository (the “main project”). The main project only needs to track the submodule’s location and version, while the submodule itself is an independent repository that can be updated and maintained separately. It’s like owning a house with a separate storage shed—you can renovate the shed independently, and the main house just needs to remember where the shed is.

Why Use Submodules?

  • Independent Maintenance: Submodules can be developed, tested, and updated separately without affecting other parts of the main project.
  • Version Control: The main project can precisely specify the submodule version (e.g., a specific commit or branch), preventing dependency code chaos.
  • Reusability: Multiple main projects can share the same submodule. When the submodule is updated, the main project only needs to sync the version.

How to Use Git Submodules?

1. Add a Submodule to the Main Project

Suppose you have a main project my_project and want to add a third-party utility library tool-lib as a submodule, located at https://github.com/example/tool-lib.git, under the libs/tool-lib directory in the main project.

Execute the command:

# Run this in the main project directory
git submodule add https://github.com/example/tool-lib.git libs/tool-lib
  • The add parameter creates the submodule. The URL https://github.com/example/tool-lib.git is the submodule’s repository address, and libs/tool-lib is its path in the main project.
  • After execution, the main project automatically generates two files:
  • .gitmodules: Stores submodule metadata (repository URL, path, etc.).
  • .git/config: Adds submodule configuration.

Commit these files to the main project repository:

git add .gitmodules libs/tool-lib/.git
git commit -m "Add submodule tool-lib"

2. Clone a Main Project with Submodules

If someone clones your main project and wants to include submodule content, use the --recursive flag to clone submodules recursively:

git clone --recursive https://github.com/yourname/my_project.git

If you forget --recursive, the submodule directory will be empty after cloning. Manually initialize and pull submodule content:

git clone https://github.com/yourname/my_project.git
cd my_project
git submodule update  # Pull submodule content

3. Update Submodules

When the submodule repository has new commits, update the submodule in the main project:

Method 1: Manual Update

cd libs/tool-lib  # Navigate to the submodule directory
git pull  # Fetch the latest code from the submodule repository

Return to the main project and update the submodule’s version record:

cd ..  # Return to the main project directory
git add libs/tool-lib  # Stage the submodule version change
git commit -m "Update submodule tool-lib to latest version"

Method 2: Automatic Update with Git
Execute in the main project directory:

git submodule update

This command automatically pulls updates in the submodule directory and updates the version recorded in the main project.

4. Remove a Submodule

To completely remove a submodule from the main project:

  1. Delete the submodule directory:
   rm -rf libs/tool-lib
  1. Clean main project configuration:
    - Open .gitmodules and delete the submodule’s configuration (e.g., the [submodule "libs/tool-lib"] section).
    - Remove the submodule from Git config:
     git config --remove-section submodule.libs/tool-lib
  1. Remove from the main project’s Git index:
   git rm --cached libs/tool-lib
  1. Commit the main project changes:
   git commit -m "Remove submodule tool-lib"
  1. Clean up residual files:
   rm -rf .git/modules/libs/tool-lib  # Delete submodule cache files

Common Issues & Notes

  • Submodule Updated but Main Project Unchanged?
    After changing submodule content, the main project must re-stage the submodule version. Ensure you run git add <submodule path> and git commit.

  • Submodule Shows “detached HEAD” (Detached HEAD)?
    This occurs when the submodule is in a “detached HEAD” state (not on a branch). Enter the submodule directory and run git checkout master (or your target branch).

  • Avoiding Conflicts in Multi-Person Collaboration
    Submodule versions are controlled by the main project’s commit hash. Following the workflow “update submodule → commit main project → merge” prevents conflicts.

Summary

Git Submodules are a powerful tool for managing project dependencies, especially for independently maintained codebases. The core workflow can be summarized as: Add submodule → Clone main project (with recursive flag) → Update submodule → Commit main project version. Master these basic operations to easily reuse and manage dependency code in your projects, avoiding repetitive work and version chaos.

Xiaoye