Tower Icon

Introduction to Git Submodules

Submodules help you to keep external libraries cleanly separated from your own code. Although generally a great feature, submodules can be quite difficult to work with from the command line.
Tower rounds off a lot of sharp edges around submodules.
Understanding how submodules work in general is key to using them anywhere - on the command line or in Tower.


How Git submodules work

Git submodules are just other Git repositories that are cloned somewhere into your project’s working tree. Each submodule is registered in a special configuration file called .gitmodules in your project’s root directory, containing the remote repository URL and the path where it resides in your work tree. This makes your repository the super repository for all submodules.

Git looks at the currently checked out revision of your submodule repository and records this information – the revision pointer – in its tree under the submodule path which can then be committed just as any other change.

With this information, other contributors can re-create each submodule’s state for each revision. Each contributor has to initially clone each submodule, though, as only the revision for an external repository is committed and not the repository itself.
If you want to use a different version of the library in your project, say 1.1 instead of 1.0, you simply check out the revision you want in the submodule and commit the modified revision pointer of the submodule.
When working with submodules, you will encounter the term “update submodule”. This operation will try to check out the revision that is currently recorded in the Git index. It will also fetch the submodule repository if the revision is not known (e.g. after a merge).



The Trouble with Submodules

Managing submodules is cumbersome. One of the drawbacks with Git submodules is that Git does not automatically update the revision pointer of a submodule in your working tree if the information about it changes (like it does for files), leaving your repository in an inconsistent state: the exact code of a submodule at a specific revision may be critical to the super repository.

For example, when you receive a change to the revision pointer of a submodule (e.g. through a merge or rebase, checkout or reset), Git will leave your submodule’s pointer where it was before the operation, creating a “Modified” status for it, as your current revision pointer is still the old one. You need to manually update the submodule every time after such operations to have your revision pointer be moved to the correct commit.

In such a case, it can be very hard to figure out what revision a submodule is supposed to point to and if you are not familiar with Git submodules there is also a good chance you may accidentally revert the change.

Also, when you switch to a branch where a particular submodule does not exist, Git will leave the submodule directory in your working tree as an untracked folder. Again, this creates an opportunity for users to mess things up.

There may be reasons for Git not to keep submodules in sync, but this is where Tower mostly improves on the behavior of submodules.


Related Topics

Managing Submodules

Fetching Submodule data

Moving the revision pointer for a Submodule

Updating Submodules