Suppose you have a repository called mainrepo and another repository called subrepo that you want to use inside mainrepo. You can just clone subrepo inside mainrepo and use it. However, if subrepo gets updated frequently, then you will have to clone it everytime and replace it inside mainrepo. If you want to view the history of commits made to subrepo , then you need to go to the remote repository where you cloned it from and see it there. And if you make any changes to the subrepo, then those changes will be part of your mainrepo and not your subrepo. You can see how this can get difficult to maintain. For cases like these, using submodule makes it easier to manage.
Adding a submodule
After cloning the subrepo, we can add it as a submodule within our mainrepo.
git submodule add https://github.com/jiteshvm/subrepo subrepo
Its important to know what changes were made to our git repo because removing a submodule is not as straightforward as adding a submodule.
Lets first do a git status in the mainrepo
$ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: .gitmodules new file: subrepo
The .gitmodules file contains an entry for each submodule added to this repository :
[submodule "subrepo"] path = subrepo url = https://github.com/jiteshvm/subrepo branch = master
There’s also a new entry called subrepo. If you check the directory, you wont find a file with that name. This is because when a submodule is added, git doesnt track the contents of the submodule directory from mainrepo. Instead, it treats it as a file which is used to track the commit to which this submodule currenly points at. You can see this by either doing a diff or checking the contents of .git/modules/subrepo/FETCH_HEAD file.
$ git diff --cached subrepo diff --git a/subrepo b/subrepo new file mode 160000 index 0000000..ca70dc9 --- /dev/null +++ b/subrepo @@ -0,0 +1 @@ +Subproject commit ca70dc947a4611af400cf4cbb70d464c7302fda0
It also created a directory called subrepo inside .git/modules/ and an entry is added in .git/config file :
[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true [submodule "subrepo"] url = /Users/jitesh/gitsubmodules/subrepo active = true
Removing a submodule
There is no straightforward way to remove a submodule from the mainrepo. To completely remove a submodule, the .gitmodules file, the .git/config file and the modules directory all need to be updated. The following 3 commands does that :
$ git submodule deinit -f subrepo/ Cleared directory 'subrepo' Submodule 'subrepo' (/Users/jitesh/gitsubmodules/subrepo) unregistered for path 'subrepo' $ git rm -f subrepo/ rm 'subrepo' $ rm -rf .git/modules/subrepo/