Git Submodules

Git sub­mod­ules allow you to access an exter­nal Git repos­i­to­ry inside of a dif­fer­ent project. This is help­ful with keep­ing code­bas­es sep­a­rate while allow­ing for an eas­i­er workflow.

The sub­mod­ule func­tion­al­i­ty works sim­i­lar­ly to svn:externals except that sub­mod­ules are locked to a revi­sion and don’t update auto­mat­i­cal­ly is the linked repos­i­to­ry does.

Adding a Sub­mod­ule #

To add a sub­mod­ule, you use the add com­mand and pass in the loca­tion of the Git repos­i­to­ry 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 set­ting for each sub­mod­ule you define. Here’s what it would look like for the sub­mod­ule we just added:

	[submodule "other_project"]
	path = other_project
	url = https://myotherproject.com/other_project.git

The .gitmodules file will be added com­mit­ted to the repos­i­to­ry because it’s how any­one who clones the repos­i­to­ry will know about the sub­mod­ules. You will also see a ref­er­ence to the sub­mod­ule in your .git/config direc­to­ry (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 new­ly cre­at­ed sub­di­rec­to­ry and .gitmodules file will show up as staged and ready to be includ­ed in the next commit.

If a col­lab­o­ra­tor want­ed to clone the project and get the sub­mod­ule con­tents, too, she would need to com­plete a few steps first. For that rea­son, it’s impor­tant that any includ­ed sub­mod­ules are doc­u­ment­ed clear­ly and instruc­tions giv­en if you’re first intro­duc­ing sub­mod­ules to your team.

Cloning a Repos­i­to­ry with Sub­mod­ules #

To suc­cess­ful­ly clone a repos­i­to­ry with sub­mod­ules, the devel­op­er will need to do the fol­low­ing steps.

$ git clone https://mysite.com/my_project.git

This will clone the repos­i­to­ry as per usu­al, how­ev­er, the sub­mod­ule will only be a shell and not con­tain the submodule’s repos­i­to­ry contents.

To make the par­ent repos­i­to­ry aware of the sub­mod­ule, we need to ini­tial­ize it:

$ git submodule init

With that done, we can pull down the sub­mod­ule contents:

$ git submodule update

All of this can done sim­pli­fied by com­bin­ing the init and update com­mands into one:

$ git submodule update --init

To make things even sim­pler, you can tell Git to recur­sive­ly clone a repos­i­to­ry, which will include any sub­mod­ules it finds. This com­bine 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 recur­sive­ly for every sub­mod­ule it finds. 

Notes on Sub­mod­ules #

Because of sub­mod­ules are sta­t­i­cal­ly point­ed” at a spe­cif­ic com­mit object, you need ensure that you push any changes to the sub­mod­ule project before you push up changes to the par­ent project. If you don’t, you’ll have a par­ent project link­ing a sub­mod­ule at a com­mit object that doesn’t yet exist in a remote repository.