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
.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
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
--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.