Git Submodules
Git submodules allow you to access an external Git repository inside of a different project. This is helpful with keeping codebases separate while allowing for an easier workflow.
The submodule functionality works similarly to svn:externals except that submodules are locked to a revision and don’t update automatically is the linked repository does.
Adding a Submodule #
To add a submodule, you use the add
command and pass in the location of the Git repository you’d like to add as a submodule.
$ git submodule add https://myotherproject.com/other_project.git
You will have a .gitmodules
file in your project root that will hold the setting for each submodule you define. Here’s what it would look like for the submodule we just added:
[submodule "other_project"]
path = other_project
url = https://myotherproject.com/other_project.git
The .gitmodules
file will be added committed to the repository because it’s how anyone who clones the repository will know about the submodules. You will also see a reference to the submodule in your .git/config
directory (which is local only).
$ cat .git/config
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[submodule "server-configs-apache"]
url = https://github.com/ryanirelan/server-configs-apache
The newly created subdirectory and .gitmodules
file will show up as staged and ready to be included in the next commit.
If a collaborator wanted to clone the project and get the submodule contents, too, she would need to complete a few steps first. For that reason, it’s important that any included submodules are documented clearly and instructions given if you’re first introducing submodules to your team.
Cloning a Repository with Submodules #
To successfully clone a repository with submodules, the developer will need to do the following steps.
$ git clone https://mysite.com/my_project.git
This will clone the repository as per usual, however, the submodule will only be a shell and not contain the submodule’s repository contents.
To make the parent repository aware of the submodule, we need to initialize it:
$ git submodule init
With that done, we can pull down the submodule contents:
$ git submodule update
All of this can done simplified by combining the init
and update
commands into one:
$ git submodule update --init
To make things even simpler, you can tell Git to recursively clone a repository, which will include any submodules it finds. This combine all of the steps we did before:
$ git clone --recursive https://mysite.com/my_project.git
The --recursive
flag will run git submodule update --init
recursively for every submodule it finds.
Notes on Submodules #
Because of submodules are “statically pointed” at a specific commit object, you need ensure that you push any changes to the submodule project before you push up changes to the parent project. If you don’t, you’ll have a parent project linking a submodule at a commit object that doesn’t yet exist in a remote repository.