Many developers already use Git to manage their codebase, but what about Git submodules? How do you use them and why? In this post, I will provide a basic tutorial on creating one, as well as explain why you would use a Git submodule in the first place. Before we begin, let me explain what a Git submodule is.
A Git submodule is a git tool that allows a user to essentially add a Git repository as a subdirectory of another Git repository. The subdirectory repository will have its own Git system, which means it will have its own commits history, independent from your main repository. This allows you to be able to set your subdirectory to refer to a specific commit you may want to work with.
How to use them
How do you use a Git submodule? First, let’s create one under a repository called House. Let’s say we want to add a submodule called Room under the House repository. To do so, you would use the command git submodule add with the absolute or relative URL of the project you want to add as a submodule. In this case:
git submodule add https://github.com/<user>/Room.git lib/Room
Let’s break it down:
- git submodule add – the syntax to add a Git submodule
- https://github.com/<user>/Room.git – the repository that is going to be added as a submodule
- lib/Room – the path where the submodule repository will be added to in the House repository (optional). If a path is not provided, the submodule will default to the same name as its repository.
If we look into the House repository, we’ll see the subdirectory Room repository like so:
Room @ 7b7b0d7
When you first add a submodule, you may not see anything inside the subfolder, depending on your Git version. In order to fill the submodule with the contents of the submodule’s repository, the submodule must be initialized with: git submodule init. After initialization, you’ll need to update your submodule to pull the contents and latest updates from its repository with the command: git submodule update.
If you do a git status, you will now notice two things: lib/Room, the path to the submodule, as well as a new file called .gitmodules—This is the configuration file that shows how your project is mapped. If we look into the file, we’ll see something like this:
path = lib/room
url = https://github.com/<user>/Room.git
Why do we use submodules?
Now that we’ve created a Git submodule, let’s answer the question: Why? Why do we use Git submodules in the first place? In most cases, Git submodules are used when your project becomes more complex, and while your project depends on the main Git repository, you might want to keep their change history separate.
Using the above as an example, the Room repository depends on the House repository, but they operate separately. By using the Room as a submodule, I can do whatever I want to my Room without having it affect my House.
Let’s translate the above scenario to something that might happen in development. Let’s say I want to include a library’s source code in my project, but I don’t want to use it as is. Maybe I want to customize it, but customizing the library’s code can lead to difficult issues, such as having to integrate the pulled changes from the library. For example, If I copied the library’s codebase into my project, I won’t be able to easily integrate new changes from the library’s codebase updates. In this case, I would use a Git submodule—I can have my project depend on the library, but whatever I do on my project is separate from the library.
As we come to the end of this post, there are a few things that you should keep in mind when using Git submodules:
- If you have collaborators that work with the submodule, make sure everyone downloads and updates the contents to ensure they have the latest and greatest. This is especially important if one person makes any changes to the submodule’s repository, as the updates are not seen by the collaborators.
- Changes in submodules are not tracked by the main repository. This requires you to change into the directory where the changes were made.