A git repo inside another git repo? Yes! With GIT Submodules!

Have you ever wanted to have a git repository included inside another git repository?

And the did git tell you something like this?

hint: You've added another git repository inside your current repository.
hint: Clones of the outer repository will not contain the contents of
hint: the embedded repository and will not know how to obtain it.

I guess you’re unlucky then! (pardon me! I am sarcastic sometimes 😊)

Humour is a life necessity

But don’t worry! As strange as it sounds that git disallows having a git repository inside a git repository, but the git team did this knowingly – because they wanted to make sure, no duplicated code gets tracked and similar stuff.

That’s why, they named it…

Git submodules

And it is exactly as it sounds like.

A git repository inside a git repository.

By using git submodules you will have the following setup:

  • a main git’s repository
  • a submodules’ git repository

Adding a submodule

cd yourself into a main repository’s root and add a submodule just like so:

git submodule add <repository-url>

Cloning into '<repository-name>'… remote: 
Counting objects: 11, done. remote: 
Compressing objects: 100% (10/10), done. remote: 
Total 11 (delta 0), reused 11 (delta 0) 
Unpacking objects: 100% (11/11), done. 
Checking connectivity… done.

You have just added “a git repository inside your git repository” – bravo! 🥳 Or in other words, you have just created a git submodule.

Now run git status to see, what have just happened:

$ git status

On branch master 
Your branch is up-to-date with 'origin/master'. 

Changes to be committed: (use "git reset HEAD …" to unstage)

new file: .gitmodules
new file: <repository-name>

There are two changes:

  • a new file “.gitsubmodules”
  • a new directory <repository-name>

.gitmodules file

In your main repository, there will be a new file called .gitmodules

It will contain just a name of the submodule and it’s repository url, for example something like this

[submodule "random-string"]
    path = random-string
    url = git@github.com:hanakivan/random-string.git
[submodule "array-range"]
    path = array-range
    url = git@github.com:hanakivan/array-range.git
[submodule "array-range-es6"]
    path = array-range-es6
    url = git@github.com:hanakivan/array-range-es6.git

A submodule directory

It is a directory of your submodule that you have jut checked out. You can go work in it, commit your changes and simply push it.

Then go to the main repository, go for git status and you will see the following:

-Subproject commit 4a4f15217e59899cb7f04cdbd1cab8e1b1045e12
+Subproject commit 556d41b5389984a1dbeecd94a161e3df53597666

This you need to commit as well – and this will be committed insides the main repository so as it can keep track of the latest commits of the submodules

Remove a submodule

Should be pretty straightfoward:

cd <main-repository-filder>
git rm <submodule-name>

After this git will remove the submodule’s dir from the main repository root and will also modify .gitmodules file by removing the reference link for the submodule’s repository.

Wrap up

The decision is up to you, you can start using git submodules, but you can go for a totally different approach, like using a npm or packagist for your packages and avoiding submodules at all.

They have pretty vast documentation and certainly you can accomplish a lot with it, but if you need to do some advanced stuff, I would argue to avoid using this completely (I’d rather have duplicated commits than deal with this kind of stuff 😂) – but hey, if complexity is not an issue for you – as the famous saying goes De gustibus non est disputandum.

Stay up to date.

Yours in coding,

Ivan