Git‎ > ‎

Submodules

At work, we have one big git repository for all of our code.  We also use other git repositories as a part of our code, which git supports as submodules.  This is super handy and we're able to not only point to a specific commit, but we also can move forward or backward in the other repository's history and then run our tests to make sure our code still interfaces properly with the other repository.  Because it is a submodule, your repository doesn't grow nor does it contain the submodule's actual history; your repository only contains a reference to where the submodule exists and what the commit hash you want to use.

Setting Up A Submodule

You can clone another git repository into your repository with the "git submodule" command.  You can also specify the destination directory where the other repo will be located.  Let's put the PHPTools repository into the "other_libraries/phptools" directory.  First, go to the top level of your repository, then you can run these commands.

git submodule add https://github.com/chrismcmacken/phptools other_libraries/phptools
git submodule init


This will put you on the most recent commit of the master branch.  If you go into other_libraries/phptools you can use that repository as you would normally.  If you have access, you can pull, commit, push, etc.  However, from outside that repository it is treated differently.  More on that later.

The "git submodule init" adds information about the submodule to your parent repository's .git/config file.

Let's make sure that we get the submodule committed.

git add .gitmodules other_libraries/phptools
git commit -m 'Adding PHPTools as a submodule'

Working With A Submodule

Let's say you need to commit a change to the repository in the submodule.  Depending on where you cloned it from and if you have access, you may be able to just change into the "other_libraries/phptools" directory, make your changes, then use "git commit" and "git push" to send your changes to origin.

Even if you don't have access to change the repository, you always can pull the latest changes down.  "git fetch" in the "other_libraries/phptools" directory will get the latest changes and "git checkout origin/master" moves you to the latest commit.

At this point you should test your code to make sure the updated library will still work and do everything that you expect.  Once you are satisfied, you can make this official by changing the commit hash for the submodule.  Go back to your parent repository and a "git status" will show you that the submodule has changed.  A "git commit" of your submodule will write the change to the history and then you can push/pull as normal and others will pick up the change to the submodule.

Ideally, at this point they will maybe run "git submodule init" and "git submodule update" so their submodules get updated properly too.

Changing Submodule Origin URL

You can point to your github account instead of using the generic, anonymous HTTPS access by editing the .git/config file in the submodule's repository and look for the [remote "origin"] section and change the value of the url key.  Since this doesn't generate a commit nor uncommitted changes, there's no worry about messing up the parent repository.

Automatic Submodule Updates

As you switch back and forth with different branches, you will find that you use "git submodule update" an awful lot.  Git can handle this for you by using its hooks.  Go to your parent repository's .git/hooks directory.  Edit the files post-checkout and post-merge (if they don't exist, create them) and add these lines:

#!/bin/bash
git submodule init
git submodule update


Now when you change branches, run a pull, or perform a merge, the submodules should be updated appropriately.
Comments