Instantly share code, notes, and snippets.

Embed
What would you like to do?
Git Submodules basic explanation

Git Submodules basic explanation

Why submodules?

In Git you can add a submodule to a repository. This is basically a repository embedded in your main repository. This can be very useful. A couple of advantages of using submodules:

  • You can separate the code into different repositories.

    Useful if you have a codebase with big components, you could make a component a submodule. This way you'll have a cleaner Git log (commits are specific to a certain component).

  • You can add the submodule to multiple repositories.

    Useful if you have multiple repositories that share the same components. With this approach you can easily update those components in all the repositories that added them as a submodule. This is a lot more convienient than copy-pasting the code into the repositories.

Basics

When you add a submodule in Git, you don't add the code of the submodule to the main repository, you only add information about the submodule that is added to the main repository. This information describes which commit the submodule is pointing at. This way, the submodule's code won't automatically be updated if the submodule's repository is updated. This is good, because your code might not work with the latest commit of the submodule, it prevents unexpected behaviour.

Adding a submodule

You can add a submodule to a repository like this:

git submodule add git@github.com:url_to/awesome_submodule.git path_to_awesome_submodule

With default configuration, this will check out the code of the awesome_submodule.git repository to the path_to_awesome_submodule directory, and will add information to the main repository about this submodule, which contains the commit the submodule points to, which will be the current commit of the default branch (usually the master branch) at the time this command is executed.

After this operation, if you do a git status you'll see two files in the Changes to be committed list: the .gitmodules file and the path to the submodule. When you commit and push these files you commit/push the submodule to the origin.

Getting the submodule's code

If a new submodule is created by one person, the other people in the team need to initiate this submodule. First you have to get the information about the submodule, this is retrieved by a normal git pull. If there are new submodules you'll see it in the output of git pull. Then you'll have to initiate them with:

git submodule init

This will pull all the code from the submodule and place it in the directory that it's configured to.

If you've cloned a repository that makes use of submodules, you should also run this command to get the submodule's code. This is not automatically done by git clone.

Pushing updates in the submodule

The submodule is just a separate resository. If you want to make changes to it, you should make the changes in this repository and push them like in a regular Git repository (just execute the git commands in the submodule's directory). However, you should also let the main repository know that you've updated the submodule's repository, and make it use the latest commit of the repository of the submodule. Because if you make new commits inside a submodule, the main repository will still point to the old commit.

So, if you want to have these changes in your main repository too, you should tell the main repository to use the latest commit of the submodule. Now how do you do this?

So you've made changes in the submodule's repository and committed them in its repository. If you now do a git status in the main repository, you'll see that the submodule is in the list Changes not staged for commit and it has the text (modified content) behind it. This means that the code of the submodule is checked out on a different commit than the main repository is pointing to. To make the main repository point to this new commit, you just add this change with git add and then commit and push it.

Keeping your submodules up-to-date

If someone updated a submodule, the other team-members should update the code of their submodules. This is not automatically done by git pull, because with git pull it only retrieves the information that the submodule is pointing to another commit, but doesn't update the submodule's code. To update the code of your submodules, you should run:

git submodule update

What happens if you don't run this command?

If you don't run this command, the code of your submodule is checked out to an old commit. When you do git status you will see the submodule in the Changes not staged for commit list with the text (modified content) behind it. This is not because you changed the submodule's code, but because its code is checked out to a different commit. So Git sees this as a change, but actually you just didn't update the submodule's code. So if you're working with submodules, don't forget to keep your submodules up-to-date.

Making it easier for everyone

It is sometimes annoying if you forget to initiate and update your submodules. Fortunately, there are some tricks to make it easier:

git submodule update --init

This will update the submodules, and if they're not initiated yet, will initiate them.

You can also have submodules inside of submodules. In this case you'll want to update/initiate the submodules recursively:

git submodule update --init --recursive

This is a lot to type, so you can make an alias:

git config --global alias.update '!git pull && git submodule update --init --recursive'

Now whenever you execute git update, it will execute a git pull and a git submodule update --init --recursive, thus updating all the code in your project.

@Noitidart

This comment has been minimized.

Show comment
Hide comment
@Noitidart

Noitidart Mar 15, 2016

I had issues updating the submodule to the latest master, I learned the difference here - http://stackoverflow.com/a/5828396/1828637

Great gist though! I learned everything else from here!

Noitidart commented Mar 15, 2016

I had issues updating the submodule to the latest master, I learned the difference here - http://stackoverflow.com/a/5828396/1828637

Great gist though! I learned everything else from here!

@PandaWood

This comment has been minimized.

Show comment
Hide comment
@PandaWood

PandaWood Feb 20, 2017

Could you add how to remove submodules? I have this odd situation where I copied a git repository (just the code) into another. I had no intention of creating a submodule, I just wanted the code. But it appears I now have a submodule! Not sure how to "unsubmodule" it.
I get these warnings "unable to rmdir..." etc as a result and the code that I need isn't being committed.

PandaWood commented Feb 20, 2017

Could you add how to remove submodules? I have this odd situation where I copied a git repository (just the code) into another. I had no intention of creating a submodule, I just wanted the code. But it appears I now have a submodule! Not sure how to "unsubmodule" it.
I get these warnings "unable to rmdir..." etc as a result and the code that I need isn't being committed.

@FaceDeer

This comment has been minimized.

Show comment
Hide comment
@FaceDeer

FaceDeer Feb 27, 2017

I second PandaWood's question. I'm doing some work with a modpack for a game that pulls together a couple of separate stand-alone git repositories, and I'm quite sure that at some point in the future I'll be wanting to remove as well as add as the modpack evolves.

FaceDeer commented Feb 27, 2017

I second PandaWood's question. I'm doing some work with a modpack for a game that pulls together a couple of separate stand-alone git repositories, and I'm quite sure that at some point in the future I'll be wanting to remove as well as add as the modpack evolves.

@DreadKnight

This comment has been minimized.

Show comment
Hide comment
@DreadKnight

DreadKnight Mar 14, 2017

Thanks for the explanation! :-)

DreadKnight commented Mar 14, 2017

Thanks for the explanation! :-)

@ellingtonjp

This comment has been minimized.

Show comment
Hide comment
@ellingtonjp

ellingtonjp Apr 11, 2017

This is an excellent explanation, thank you! I will refer newcomers to this.

I think you are missing one important point, however. When working on submodules, after an initial git submodule update --init or git submodule update, the submodule will be in a detached HEAD state. It is necessary to go into the submodule and checkout the desired branch, make your commits, and then push. Then you can point the main repository to the new submodule commits.

Additionally you may emphasize the importance of pushing the submodule code as well as pointing the main repo to it. For example, if you commit to the submodule (without pushing) and point the main repo to those commits, you'll be in trouble because others won't have the submodule commits that your main repo is now pointing to.

ellingtonjp commented Apr 11, 2017

This is an excellent explanation, thank you! I will refer newcomers to this.

I think you are missing one important point, however. When working on submodules, after an initial git submodule update --init or git submodule update, the submodule will be in a detached HEAD state. It is necessary to go into the submodule and checkout the desired branch, make your commits, and then push. Then you can point the main repository to the new submodule commits.

Additionally you may emphasize the importance of pushing the submodule code as well as pointing the main repo to it. For example, if you commit to the submodule (without pushing) and point the main repo to those commits, you'll be in trouble because others won't have the submodule commits that your main repo is now pointing to.

@Boopaathy

This comment has been minimized.

Show comment
Hide comment
@Boopaathy

Boopaathy May 23, 2017

Can we give path for submodule to any absolute path, which means outside the parent git repository?

Is there any option to add submodules to any desired path outside the parent git repository folder?

Boopaathy commented May 23, 2017

Can we give path for submodule to any absolute path, which means outside the parent git repository?

Is there any option to add submodules to any desired path outside the parent git repository folder?

@Samir55

This comment has been minimized.

Show comment
Hide comment
@Samir55

Samir55 May 28, 2017

Can I make the submodule contains only certain folders in my repository? I want to include one folder minizip folder found in /contrib/ from the zlib repository

Samir55 commented May 28, 2017

Can I make the submodule contains only certain folders in my repository? I want to include one folder minizip folder found in /contrib/ from the zlib repository

@rjpaulsen

This comment has been minimized.

Show comment
Hide comment
@rjpaulsen

rjpaulsen Jun 6, 2017

To remove a submodule,

  1. Remove it from the .git configuration files:
    git rm the_submodule

  2. Remove it from the modules folder. You can also do this from a UI file explorer of some type:
    rm -rf .git/modules/the_submodule

  3. You may also need to remove the subfolder in your repository.

rjpaulsen commented Jun 6, 2017

To remove a submodule,

  1. Remove it from the .git configuration files:
    git rm the_submodule

  2. Remove it from the modules folder. You can also do this from a UI file explorer of some type:
    rm -rf .git/modules/the_submodule

  3. You may also need to remove the subfolder in your repository.

@asagalSP

This comment has been minimized.

Show comment
Hide comment

asagalSP commented Jan 29, 2018

@szhao8

This comment has been minimized.

Show comment
Hide comment
@szhao8

szhao8 Feb 15, 2018

Thank you for your explanation, it's helpful!

szhao8 commented Feb 15, 2018

Thank you for your explanation, it's helpful!

@hsaih

This comment has been minimized.

Show comment
Hide comment
@hsaih

hsaih Mar 13, 2018

The article is misleading and contains many mistakes.

Below the mistakes I found, with the corrections of them:

When you add a submodule in Git, you don't add the code of the submodule to the main repository

Incorrect. Upon running git submodule add command, the submodule's code is added to the repository.

This way, the submodule's code won't automatically be updated if the submodule's repository is updated.

No. What prevents for a submodule to be updated is the .gitmodules file which stores the submodule version when the submodule was added.

First you have to get the information about the submodule, this is retrieved by a normal git pull

No. It is retrieved by git fetch conmand.

git submodule init.
This will pull all the code from the submodule

This won't pull the code. What git submodule init command does is initalizing the local git configuration with the submodules list, retrieved from the .gitmodules file. Still no submodule's code is present.

resository

typo.

Pushing updates in the submodule

The whole section is wrong. There is a conflation between commit and push git workflows and wrong use of the git add command.

This is not automatically done by git pull, because with git pull it only retrieves the information that the submodule is pointing to another commit

Incorrect. The submodule can be updated by using git pull inside the submodule's directory.

To update the code of your submodules, you should run:
git submodule update

Incorrect. To update the submodule you run git submodule update --remote

git submodule update --init
This will update the submodules, and if they're not initiated yet, will initiate them.

This won't update the submodules, what it will do is 1) initialize the git configuration with the submodules list retrieved from the .gitmodules file 2) clone the submodule repository into the project repository.

hsaih commented Mar 13, 2018

The article is misleading and contains many mistakes.

Below the mistakes I found, with the corrections of them:

When you add a submodule in Git, you don't add the code of the submodule to the main repository

Incorrect. Upon running git submodule add command, the submodule's code is added to the repository.

This way, the submodule's code won't automatically be updated if the submodule's repository is updated.

No. What prevents for a submodule to be updated is the .gitmodules file which stores the submodule version when the submodule was added.

First you have to get the information about the submodule, this is retrieved by a normal git pull

No. It is retrieved by git fetch conmand.

git submodule init.
This will pull all the code from the submodule

This won't pull the code. What git submodule init command does is initalizing the local git configuration with the submodules list, retrieved from the .gitmodules file. Still no submodule's code is present.

resository

typo.

Pushing updates in the submodule

The whole section is wrong. There is a conflation between commit and push git workflows and wrong use of the git add command.

This is not automatically done by git pull, because with git pull it only retrieves the information that the submodule is pointing to another commit

Incorrect. The submodule can be updated by using git pull inside the submodule's directory.

To update the code of your submodules, you should run:
git submodule update

Incorrect. To update the submodule you run git submodule update --remote

git submodule update --init
This will update the submodules, and if they're not initiated yet, will initiate them.

This won't update the submodules, what it will do is 1) initialize the git configuration with the submodules list retrieved from the .gitmodules file 2) clone the submodule repository into the project repository.

@icanseesharp

This comment has been minimized.

Show comment
Hide comment
@icanseesharp

icanseesharp Jun 8, 2018

Excellent article, very helpful as an introduction to submodules.
Thank you!

icanseesharp commented Jun 8, 2018

Excellent article, very helpful as an introduction to submodules.
Thank you!

@svarlamov

This comment has been minimized.

Show comment
Hide comment
@svarlamov

svarlamov Jul 18, 2018

If you're frustrated/confused with Git submodules as many devs are, check out Mdlr. It's open source tool that offers a declarative and easy alternative to the complicated and frustrating Git submodules workflow https://github.com/exlinc/mdlr

svarlamov commented Jul 18, 2018

If you're frustrated/confused with Git submodules as many devs are, check out Mdlr. It's open source tool that offers a declarative and easy alternative to the complicated and frustrating Git submodules workflow https://github.com/exlinc/mdlr

@AliYusuf95

This comment has been minimized.

Show comment
Hide comment
@AliYusuf95

AliYusuf95 Jul 26, 2018

To update a submodule version to latest version:

cd path_to_submodule
git checkout master && git pull
cd ..
git add path_to_submodule
git commit -m "updating submodule to latest"

AliYusuf95 commented Jul 26, 2018

To update a submodule version to latest version:

cd path_to_submodule
git checkout master && git pull
cd ..
git add path_to_submodule
git commit -m "updating submodule to latest"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment