Git submodules provide a nifty way to integrate a git repository within a git repository. The first time I encountered git submodules was when I was browsing Heng Li’s fermikit git repository.

Notice how the files have a @ symbol folowed by some random value. This actually indicates a git submodule within this git repository. For instance, the bfc file is actually a folder containing the bfc git repository. The seemingly random value after the @ symbol is a git hash that indicates a specific commit of the bcf git repository. This basically means this current commit of fermikit depends on the “a73dad2” commit of the bcf repository.

While this may seem fairly sophisticated, it’s actually not too difficult to get this kind of setup for your own git repository. This post will provide a primer on how to get started with using git submodules.

# Setup

All the code in this post was performed with the following git version:

git --version
git version 1.9.3 (Apple Git-50)


Let’s first create some local git repositories just for demonstration purposes.

1. Create the top-level git repository:

 mkdir ~/git-toplevel-repo
cd ~/git-toplevel-repo
git init

2. Create another git repository that will serve as the git submodule.

 mkdir ~/git-submodule-repo
cd ~/git-submodule-repo
git init


Adding a git submodule can be done using git submodule add. Let’s use the git-toplevel-repo as the top-level repository and add the git-submodule-repo as the submodule:

cd ~/git-toplevel-repo


This will create a folder with the same name as the repository name (i.e. git-submodule-repo) and also checkout the latest commit of the repository into this folder. If you now do a git status, you should see:

On branch master

Initial commit

Changes to be committed:
(use "git rm --cached <file>..." to unstage)

new file:   .gitmodules
new file:   git-submodule-repo


The git-submodule-repo folder has been added and already staged. Additionally, you will notice how a .gitmodules file has been added. If you do a cat .gitmodules

[submodule "git-submodule-repo"]
path = git-submodule-repo
url = /Users/fcchan/git-submodule-repo


This file will actually contain information regarding all the submodules that you have add to your git repository. Let’s do a quick git commit now so that we can move onto the next section:

git commit -m "First Commit"


So what happens when your git submodule changes? For instance, if you go into the git-submodule-repo and add a file:

cd ~/git-submodule-repo
touch TEST


Now, if you enter the submodule folder from the top-level git repository and run:

cd ~/git-toplevel-repo/git-submodule-repo
git pull

remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 2 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (2/2), done.
From /Users/fcchan/git-submodule-repo
ebba154..d931029  master     -> origin/master
Updating ebba154..d931029
Fast-forward
TEST | 0
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 TEST


You will see that the TEST file is added. Now if you go to the top-level git repository folder and run git status:

cd ~/git-toplevel-repo
git status

On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)

modified:   git-submodule-repo (new commits)


Git is able to identify that the git submodule has new commits to it and indicates this to you. In order to indicate that your top-level git repository should reference this specific commit of the submodule, you need to run git add git-submodule-repo. This ensures that if you were to clone this top-level repository (details of this below), then it will point to the git-submodule-repo commit that contains the TEST file. So let’s do this:

git add git-submodule-repo
git commit -m "Updating Submodule Commit"


# Cloning a Git Repository with Git Submodules

Now let’s experiment with cloning a git repository that contains a git submodule:

git clone ~/git-toplevel-repo ~/git-clone-test


If you actually go into the git-clone-test folder, you will see the git-submodule-repo folder. But it is empty! Where are my README and TEST files?

This was counter-initutive to me the first time I did this, but the key is you need to first initialize the submodules and then run an update:

cd ~/git-clone-test
git submodule init
git submodule update


Now you should be able to see the TEST and README files in the git-submodule-repo folder.

# Summary

That’s it! Hopefully, you now have the basics on how to get started with using git submodules

For a more detailed reference, I would recommend the following references: