Skip to main content

Submodules

Submodules are a useful feature of git, and allow us to nest projects within our own project. A good example of a project that would take advantage of this is a dotfiles repository - mine can be found on GitLab and has several submodules.

I've recently been working on kot, a linux dotfiles CLI tool, and I have been testing it with my dotfiles repository within a docker container. I thought this was a good chance to write down some useful commands for dealing with git submodules.

If you want a repository to test these commands, feel free to clone kot and play around with the submodules within.

git clone https://gitlab.com/shaunrd0/kot
cd kot

To show a status of all submodules -

git submodule status --recursive

-7877117d5bd413ecf35c86efb4514742d8136843 dot (heads/master)
-826d5691ac7d36589591314621047b1b9d89ed34 dot/.vim/bundle/Colorizer
-3ea887d2f4d43dd55d81213517344226f6399ed6 dot/.vim/bundle/ale
-293a1062274a06be61797612034bd8d87851406e dot/.vim/bundle/clang_complete
-d80e8e2c1fa08607fa34c0ca5f1b66d8a906c5ef dot/.vim/bundle/supertab
-afb8db4f81580771c39967e89bc5772e72b9018e dot/.vim/bundle/unicode.vim
-cb1bc19064d3762e4e08103afb37a246b797d902 dot/.vim/bundle/vim-airline
-d148d42d9caf331ff08b6cae683d5b210003cde7 dot/.vim/bundle/vim-airline-themes
-b2a0450e23c63b75bbeabf4f0c28f9b4b2480689 dot/.vim/bundle/vim-signify

So I have dot as a submodule, and dot also has several submodules we inherit with the --recursive option. The same command without recursion is shown below

git submodule status

-7877117d5bd413ecf35c86efb4514742d8136843 dot (heads/master)

Notice in all of the output below, there is a minus sign - before each submodule. This means they have not been initialized. To summarize the meaning of this output, I'll quote from man git-submodule

This will print the SHA-1 of the currently checked out commit for each submodule, along with the submodule path and the output of git describe for the SHA-1. Each SHA-1 will possibly be prefixed with - if the submodule is not initialized, + if the currently checked out submodule commit does not match the SHA-1 found in the index of the containing repository and U if the submodule has merge conflicts.

To update and initialize all submodules recursively, we can use the following command

git submodule update --init --recursive        

Submodule 'dotfiles/dot' (https://gitlab.com/shaunrd0/dot) registered for path 'dotfiles/dot'
Cloning into '/home/kapper/Code/kotd/dotfiles/dot'...
warning: redirecting to https://gitlab.com/shaunrd0/dot.git/
Submodule path 'dotfiles/dot': checked out '7877117d5bd413ecf35c86efb4514742d8136843'
Submodule '.vim/bundle/Colorizer' (https://github.com/chrisbra/Colorizer) registered for path 'dotfiles/dot/.vim/bundle/Colorizer'
Submodule '.vim/bundle/ale' (https://github.com/dense-analysis/ale) registered for path 'dotfiles/dot/.vim/bundle/ale'
Submodule '.vim/bundle/clang_complete' (https://github.com/xavierd/clang_complete) registered for path 'dotfiles/dot/.vim/bundle/clang_complete'
Submodule '.vim/bundle/supertab' (https://github.com/ervandew/supertab) registered for path 'dotfiles/dot/.vim/bundle/supertab'
Submodule '.vim/bundle/unicode.vim' (https://github.com/chrisbra/unicode.vim) registered for path 'dotfiles/dot/.vim/bundle/unicode.vim'
Submodule '.vim/bundle/vim-airline' (https://github.com/vim-airline/vim-airline) registered for path 'dotfiles/dot/.vim/bundle/vim-airline'
Submodule '.vim/bundle/vim-airline-themes' (https://github.com/vim-airline/vim-airline-themes) registered for path 'dotfiles/dot/.vim/bundle/vim-airline-themes'
Submodule '.vim/bundle/vim-signify' (https://github.com/mhinz/vim-signify) registered for path 'dotfiles/dot/.vim/bundle/vim-signify'
Cloning into '/home/kapper/Code/kotd/dotfiles/dot/.vim/bundle/Colorizer'...
Cloning into '/home/kapper/Code/kotd/dotfiles/dot/.vim/bundle/ale'...
Cloning into '/home/kapper/Code/kotd/dotfiles/dot/.vim/bundle/clang_complete'...
Cloning into '/home/kapper/Code/kotd/dotfiles/dot/.vim/bundle/supertab'...
Cloning into '/home/kapper/Code/kotd/dotfiles/dot/.vim/bundle/unicode.vim'...
Cloning into '/home/kapper/Code/kotd/dotfiles/dot/.vim/bundle/vim-airline'...
Cloning into '/home/kapper/Code/kotd/dotfiles/dot/.vim/bundle/vim-airline-themes'...
Cloning into '/home/kapper/Code/kotd/dotfiles/dot/.vim/bundle/vim-signify'...
Submodule path 'dotfiles/dot/.vim/bundle/Colorizer': checked out '826d5691ac7d36589591314621047b1b9d89ed34'
Submodule path 'dotfiles/dot/.vim/bundle/ale': checked out '3ea887d2f4d43dd55d81213517344226f6399ed6'
Submodule path 'dotfiles/dot/.vim/bundle/clang_complete': checked out '293a1062274a06be61797612034bd8d87851406e'
Submodule path 'dotfiles/dot/.vim/bundle/supertab': checked out 'd80e8e2c1fa08607fa34c0ca5f1b66d8a906c5ef'
Submodule path 'dotfiles/dot/.vim/bundle/unicode.vim': checked out 'afb8db4f81580771c39967e89bc5772e72b9018e'
Submodule path 'dotfiles/dot/.vim/bundle/vim-airline': checked out 'cb1bc19064d3762e4e08103afb37a246b797d902'
Submodule path 'dotfiles/dot/.vim/bundle/vim-airline-themes': checked out 'd148d42d9caf331ff08b6cae683d5b210003cde7'
Submodule path 'dotfiles/dot/.vim/bundle/vim-signify': checked out 'b2a0450e23c63b75bbeabf4f0c28f9b4b2480689'

Now if we later return to the repository and run git submodule status --recursive and get the following output

git submodule status --recursive 

+7877117d5bd413ecf35c86efb4514742d8136843 dot (heads/master)
 826d5691ac7d36589591314621047b1b9d89ed34 dot/.vim/bundle/Colorizer (heads/master)
 3ea887d2f4d43dd55d81213517344226f6399ed6 dot/.vim/bundle/ale (v3.1.0-9-g3ea887d2)
 293a1062274a06be61797612034bd8d87851406e dot/.vim/bundle/clang_complete (v1.8-374-g293a106)
 d80e8e2c1fa08607fa34c0ca5f1b66d8a906c5ef dot/.vim/bundle/supertab (2.1-40-gd80e8e2)
 afb8db4f81580771c39967e89bc5772e72b9018e dot/.vim/bundle/unicode.vim (v20-139-gafb8db4)
 cb1bc19064d3762e4e08103afb37a246b797d902 dot/.vim/bundle/vim-airline (v0.11-354-gcb1bc19)
 d148d42d9caf331ff08b6cae683d5b210003cde7 dot/.vim/bundle/vim-airline-themes (remotes/origin/jellybeans-refactor-266-gd148d42)
 b2a0450e23c63b75bbeabf4f0c28f9b4b2480689 dot/.vim/bundle/vim-signify (v1.0-291-gb2a0450)

This means the dot project submodule has a new commit that we haven't pulled into our local project yet. To fix this, just run the command below again.

git submodule update --init --recursive

Fixing or replacing submodules can be done with the following steps.

For context, see the status of all submodules

git submodule status 

 826d5691ac7d36589591314621047b1b9d89ed34 .vim/bundle/Colorizer (heads/master)
 3ea887d2f4d43dd55d81213517344226f6399ed6 .vim/bundle/ale (v3.1.0-9-g3ea887d2)
 293a1062274a06be61797612034bd8d87851406e .vim/bundle/clang_complete (v1.8-374-g293a106)
 d80e8e2c1fa08607fa34c0ca5f1b66d8a906c5ef .vim/bundle/supertab (2.1-40-gd80e8e2)
 afb8db4f81580771c39967e89bc5772e72b9018e .vim/bundle/unicode.vim (v20-139-gafb8db4)
 cb1bc19064d3762e4e08103afb37a246b797d902 .vim/bundle/vim-airline (v0.11-354-gcb1bc19)
 d148d42d9caf331ff08b6cae683d5b210003cde7 .vim/bundle/vim-airline-themes (remotes/origin/jellybeans-refactor-266-gd148d42)
 b2a0450e23c63b75bbeabf4f0c28f9b4b2480689 .vim/bundle/vim-signify (v1.0-291-gb2a0450)

So we try to add a submodule, one that we had removed from .gitmodules and deleted the directory. But we get the error below.

git submodule add https://github.com/alexanderjeurissen/ranger_devicons .config/ranger/plugins/ranger_devicons

A git directory for '.config/ranger/plugins/ranger_devicons' is found locally with remote(s):
  origin        https://github.com/alexanderjeurissen/ranger_devicons
If you want to reuse this local git directory instead of cloning again from
  https://github.com/alexanderjeurissen/ranger_devicons
use the '--force' option. If the local git directory is not the correct repo
or you are unsure what this means choose another name with the '--name' option.

To correct the awkward start our git modules are in, we simply remove all traces of the submodule. To do this, run the following commands

git rm -r --cached .config/ranger/plugins/ranger_devicons/
rm -r .config/ranger/plugins/ranger_devicons/
rm -rf .git/modules/.config/ranger/plugins/ranger_devicons/
vim .gitmodules
vim .git/config

The first file opened by the vim command is .gitmodules within the root of your repository. REMOVE the following lines, and save the file.

# .gitmodules file in the root of your repository
[submodule ".config/ranger/plugins/ranger_devicons"]
  path = .config/ranger/plugins/ranger_devicons
  url = https://github.com/alexanderjeurissen/ranger_devicons

The second file opened by the vim command is .git/config. REMOVE the following lines, and save the file.

# .git/config from the root of your repository
[submodule ".config/ranger/plugins/ranger_devicons"]
  url = https://github.com/alexanderjeurissen/ranger_devicons
  active = true

Now you can add the submodule back again

git submodule add https://github.com/alexanderjeurissen/ranger_devicons .config/ranger/plugins/ranger_devicons

Cloning into '/home/kapper/dot/.config/ranger/plugins/ranger_devicons'...
remote: Enumerating objects: 329, done.
remote: Counting objects: 100% (91/91), done.
remote: Compressing objects: 100% (84/84), done.
remote: Total 329 (delta 37), reused 10 (delta 7), pack-reused 238
Receiving objects: 100% (329/329), 183.95 KiB | 2.11 MiB/s, done.
Resolving deltas: 100% (146/146), done.
git submodule status 

 feb2d7a90fe8aabd7ee3965d4bd67ebedceca817 .config/ranger/plugins/ranger_devicons (heads/main)
 826d5691ac7d36589591314621047b1b9d89ed34 .vim/bundle/Colorizer (heads/master)
 3ea887d2f4d43dd55d81213517344226f6399ed6 .vim/bundle/ale (v3.1.0-9-g3ea887d2)
 293a1062274a06be61797612034bd8d87851406e .vim/bundle/clang_complete (v1.8-374-g293a106)
 d80e8e2c1fa08607fa34c0ca5f1b66d8a906c5ef .vim/bundle/supertab (2.1-40-gd80e8e2)
 afb8db4f81580771c39967e89bc5772e72b9018e .vim/bundle/unicode.vim (v20-139-gafb8db4)
 cb1bc19064d3762e4e08103afb37a246b797d902 .vim/bundle/vim-airline (v0.11-354-gcb1bc19)
 d148d42d9caf331ff08b6cae683d5b210003cde7 .vim/bundle/vim-airline-themes (remotes/origin/jellybeans-refactor-266-gd148d42)
 b2a0450e23c63b75bbeabf4f0c28f9b4b2480689 .vim/bundle/vim-signify (v1.0-291-gb2a0450)