Git

Git Submodule

I find myself interacting with submodules more and more, and never spent the time to properly understand how they work.

We call “superproject” the project that will contain the submodules.

Git submodules are used for when you have a git repository inside a git repository.

Resources

Adding a new submodule

git submodule add -b (branch to track) (repo URL) 

What if you wanted to put it inside a nested folder?

You can still do it, just make sure to cd inside the right directory first.

Removing a submodule

git submodule deinit -f PATH_TO_FOLDER
rm -rf .git/modules/PATH_TO_FOLDER
git rm -f PATH_TO_FOLDER

How Submodule Changes are detected

Git sees a submodule’s changes as a particular commit from that repository.

How are submodules built into git?

Git stores information about submodules in two places (Source):

  1. .gitmodules (Changes to this file are what get propagated to other repositories)
  2. .git/config (local changers. where git actually looks when performing most commands).

Just like. .gitignore file, you will have a .gitsubmodules file to maintain the list of submodules.

Periodically updating your submodules

Run the following:

git pull
git submodule update --init --recursive --remote

The git submodule update Command

The most common command you will need to use is git submodule update, which performs the task of updating all of the local submodules you have in your copy of isaac_ros-dev. Technically, this command isn’t strictly necessary; everything it does can also be done by navigating to each individual submodule and checking out the latest version of the stable branch, but that process is very tedious when you have lots of submodules!

  1. --init: tells git to populate the folders of any new submodules that haven’t been initialized on your machine yet. Good for a fresh clone, but desn’t hurt to include this flag every time
  2. --recursive: tells git to recursively update any submodules-of-submodules and so on
  3. --remote: This flag tells git to fetch from the remote URL specified in the .gitmodules file, and then checkout the latest commit. Note: Sometimes you will want to omit it! 

Why you might not want to include --rmeote

The reason you might not want to include this flag is because it will always checkout the ‘stable’ branch specified in .gitmodules; if you are currently working on a new feature branch that hasn’t been merged to main in one of your packages and you want to stay on that non-main branch, you will want to omit the —remote flag.

Cloning a project

Initialize your local configuration file (FIRST TIME)

git submodule init

What is the point of submodule init??

In this usage, git submodule init seems to do only one thing: populate .git/config with information that is already in .gitmodules. Why can’t you just combine it with git submodule update? Stackoverflow answer. Answer: there are use cases where you want s

Fetch all the data from that project and check out the appropriate commit listed in your superproject (--recursive because submodules might contain submodules)

git submodule update --recursive

Another way

Another way to do it is by adding the --recurse-submodules flag, but I always forget. Ex:

git clone --recurse-submodules https://github.com/chaconinc/MainProject

So the main question is, if the submodule gets updated, how do you update the superproject?

  • Very easy, just commit/pull from inside the submodule, and then go to the parent git repository, and it will detect a change in terms of the commit hash
cd submodule
git pull
cd ..
git status # you will see a difference
git add .
git cm "bump submodules"