This week I have been learning about Git Submodules.
Submodules is a tool built into git. It's designed to make working with repos within repos a lot easier. Why would you be working with repos within repos? Well, let's talk about that.
Why would you use a repo inside another repo?
There are several reasons you might want to do this. For example, if you have your own component library you use across multiple projects, and you want to work on both the component library and the app itself side by side. Or on a larger project containing multiple pieces worked on by multiple teams, when you don't want code from the various sections of the project interfering with one another during the development process.
So to give a simplified example of this set up we are going to have a parent repo, and 2 child repos, childA and childB.
First off, we need to clone the parent repo. To add the two child repos as submodules of parent we are going to go into the parent and run
git add submodule <repo-address>
for each of the children, replacing
<repo-address> with the address for the repo.
Once you've done this, you'll notice a new file has been created:
.gitmodules you will notice entries for both childA and childB. Something like this:
[submodule "childA"] path = childA url = https://github.com/path/to/childA [submodule "childB"] path = childB url = https://github.com/path/to/childB
git status, you should see an entry for childA and childB being created. We can now commit and push these changes.
Congratulations! You have now set up childA and childB as submodules of your parent repo.
Now that you have the submodules set up, next time you clone parent you will see 2 empty directories, 1 for each of the children. Here is where you will start to see the benefits of using submodules.
Before using submodules, to clone any child repos, you needed to go through and run a git clone for each repo. In this example that would mean only 2 commands, but in a large project where there could be 5 or 6 child repos, it could mean quite a few commands. But with submodules, all we need to do is run one single command:
git submodule update --init
This will then go and clone all the submodule repos into their respective directories.
Now we have all our code checked out, we need to install it. Working with multiple repos this can be a pain, and very time-consuming, moving in and out of each of the repos to run
Submodules has a solution! As part of the submodules suite of functionality, git contains a
foreach command. To use it, we need to pass the command we want to run to it, in this case
npm install, and it will then run that command in each of the submodules.
git submodule foreach 'npm install'
In summary, we're going to replace all of those commands, moving in and out of repos, and using
npm install in each one, with a single command executed in the parent.
Let's take a second now and talk about
foreach. This is an incredibly useful little command as you can see.
Want to run
npm install in each child?
git submodule foreach 'npm install'
Want to switch each child to the
dev branch and pull the latest code?
git submodule foreach 'git checkout dev && git pull'
Want to stash all changes?
git submodule foreach 'git add . && git stash'
I'm sure you get the idea. Anything you want to do in every child repo can be done with 1 command.
Going back to our example, we now have a fully working version of our project, including all sub-repos, and all we needed to do is the following:
git clone https://github.com/path/to/parent cd parent git submodule update --init npm install git submodule foreach 'npm install' npm start
This was just a simple example showcasing what git submodules can do. There are plenty more useful features that I would encourage you to check out. Git themselves have some great documentation on submodules available here