Terminus by Warp
Adding a Submodule in Git

Adding a Submodule in Git

Philip Wilkinson
Philip Wilkinson
Software Engineer, Amazon

After you have created a git repository one step you may want to take is to add a submodule.  This is a way to include one git repository as a subdirectory within another repository. This allows you to combine multiple independent repositories into a single large project, providing you with a way to manage dependencies across several projects.

[#adding-a-submodule]Adding a submodule[#adding-a-submodule]

To add a submodule to an existing project, you can use the following `git submodule add` command:

 $ git submodule add <repository_url> <subdirectory>

Where the [.inline-code]<repository_url>[.inline-code] is the URL of the repository you want to add and [.inline-code]<subdirectory>[.inline-code] is the optional target path of the submodule within the main project.

For example:

 $ git submodule add https://github.com/team/vendors.git vendors

To verify that the submodule has been added to the repository you can use the [.inline-code]git status[.inline-code] command. This should show that a [.inline-code].gitmodules[.inline-code] file has been created within the parent project along with the new directory.

You can also specify which branch of the remote repository you want to add as a submodule by using the [.inline-code]-b <branch>[.inline-code] flag. This will change the command to:

 $ git submodule add -b <branch_name> <repository_url> <subdirectory>

Easily retrieve this command using Warp’s AI Command Search

If you’re using Warp as your terminal, you can easily retrieve this command using the Warp AI Command Search feature:

Entering [.inline-code]git add submodule branch[.inline-code] into the AI command search will prompt a [.inline-code]git submodule add[.inline-code] command that can then be quickly inserted into your shell by doing [.inline-code]CMD+ENTER[.inline-code].

[#tracking-submodule-changes]Tracking submodule changes[#tracking-submodule-changes]

[#tracking-a-few-submodules]Tracking changes of certain submodules[#tracking-a-few-submodules]

In some cases you may want to add several submodules to your repository but only want to track the changes made in a few of them. In this case you can take advantage of the [.inline-code]git submodule init[.inline-code] command to specify which submodules you want to update when performing the [.inline-code]git submodule update –remote[.inline-code] command. 

For example, you have a repository that has three submodules: [.inline-code]sub1[.inline-code], [.inline-code]sub2[.inline-code] and [.inline-code]sub3[.inline-code]. You may only want to retrieve updates for [.inline-code]sub1[.inline-code] and [.inline-code]sub2[.inline-code] as you want [.inline-code]sub3[.inline-code] to remain stable. For this you would use the command:

 $ git submodule init sub1 sub2

This would mean that when you perform the [.inline-code]git submodule update –remote[.inline-code] command, it will only fetch remote changes for the [.inline-code]sub1[.inline-code] and sub2[.inline-code] repositories.

[#changing-a-submodule-url]Changing the remote URL for a submodule[#changing-a-submodule-url]

An alternative use for this command is to change the remote repository URL for a submodule. This is because the [.inline-code]git submodule init[.inline-code] command creates a [.inline-code].git/config[.inline-code] file which contains the remote URL of each submodule to update from. After performing the [.inline-code]git submodule init[.inline-code] command you can edit the [.inline-code].git/config[.inline-code] file to change the URL of the submodule from which to fetch updates when performing the [.inline-code]git submodule update –remote[.inline-code] command.

[#adding-a-branch-to-a-submodule]Adding a branch to a submodule[#adding-a-branch-to-a-submodule]

A Git submodule works on a “no branch” approach, which means that each submodule uses a specific commit rather than tracking a specific branch. This can make working on the submodule difficult and tricky to manage as any new commits added to the submodule will often be lost when updating it in the future. To get around this you need to add a branch to the submodule to work on. This can be done using the commands:

 $ cd <submodule_directory>
$ git checkout <branch_name>

When making any changes to this branch and then subsequently updating the submodule, you need to add the [.inline-code]--merge[.inline-code] or [.inline-code]--rebase[.inline-code] flag to ensure that your changes are not lost. This turns the [.inline-code]update[.inline-code] command into either:

 $ git submodule update –rebase
$ git submodule update –merge

If you forget the [.inline-code]--merge[.inline-code] or [.inline-code]--rebase[.inline-code] flags, Git will just update the submodule to whatever is on the server and reset your project to a detached HEAD state. If this happens, you can go back into the directory and check out your branch again and merge or rebase [.inline-code]origin/stable[.inline-code] (or whatever remote branch you want), manually.

[#issues-with-submodules]Issues with submodules [#issues-with-submodules]

Because of their complexity, using submodules is often difficult when working within a git repository. This is complicated by two common operations:

[#switching-branches]Switching branches[#switching-branches]

Prior to Git version 2.13, switching branches in a repository containing submodules can be quite difficult. For example, if you create a new branch, add a submodule there, and then switch back to a branch without that submodule, you will still have that submodule as an untracked directory. You will then have to remove that directory and will need to run [.inline-code]git submodule update –init[.inline-code] to repopulate it when switching back to the branch.

[#switching-from-subdirectories]Switching from subdirectory to submodules[#switching-from-subdirectories]

If you have been tracking files in your project and want to move them into a submodule, then this can create issues with Git. For example, if you delete a subdirectory and then add a submodule with the same name then Git will not let you. You first need to unstage the original directory and then add the submodule. This can become further complicated when switching branches as you will need to force checkouts which can often lead to missing files in subdirectories or submodules.

[#alternatives-to-submodules]Alternatives to submodules[#alternatives-to-submodules]

Git submodules are useful as they allow you to use another project from within the project you are working on. However, they can often be difficult to manage. This means that there are several alternatives available to use:

[#git-subtree]Git subtree[#git-subtree]

[.inline-code]git subtree[.inline-code] lets you nest one repository inside another as a subdirectory and is another method for managing project dependencies. The benefits of using [.inline-code]git subtree[.inline-code] are that:

  • The sub-projects code is available right after the clone of the super project is done.
  • [.inline-code]git subtree[.inline-code] does not require new users of your project to know how submodules work.
  • [.inline-code]git subtree[.inline-code] does not add new metadata files as git submodules do.
  • Contents of the module can be modified without having a separate copy of the dependency somewhere else.
  • The subdirectory created by the subtree can be committed to, branched, and merged with the project in any way you want.

But there are also drawbacks:

  • You must learn about a new merge strategy ([.inline-code]git subtree[.inline-code])
  • Contributing code back to the sub-projects can still be complicated
  • The responsibility of not mixing super and sub-project code in commits lies with the user

[#git-slave] Git slave [#git-slave]

Git slave is a “script for coordinated version control of large projects” which combines code from multiple independent repositories using Git. This means that it provides a wrapper around git that manages a tree of directories with multiple “sub” repositories in the directories so that you can control all “sub” repositories from the “main” repository itself. This is useful when you want to perform operations such as adding tags and branches and performing pushes and pulls to all repositories at the same time. The main drawback of this is it may be difficult to operate on a Windows machine in particular and it requires Perl. 

[#nested-repositories]Nested repositories[#nested-repositories]

If your software has a plugin architecture, with each plugin being its own sub-directory, it can often make sense to [.inline-code]git-ignore[.inline-code] these plugin directories and make each of them their own git repository. This way ensures that all the files form a single directory tree but are managed by different git repositories. The main downside to this however is if you specify any of the sub-repositories code in the main repository, other developers need to know their file relationship to run the main repository.

Experience the power of Warp

  • Write with an IDE-style editor
  • Easily navigate through output
  • Save commands to reuse later
  • Ask Warp AI to explain or debug
  • Customize keybindings and launch configs
  • Pick from preloaded themes or design your own
brew install --cask warp
Join the Windows waitlist:
Success! You will receive an email from Warp when the release is available to download.
Oops! Something went wrong while submitting the form.
Join the Linux waitlist:
Success! You will receive an email from Warp when the release is available to download.
Oops! Something went wrong while submitting the form.
Join the Linux waitlist or join the Windows waitlist
Join the Windows waitlist:
Success! You will receive an email from Warp when the release is available to download.
Oops! Something went wrong while submitting the form.