Git Submodule Cheatsheet

Kenichi Shibata
Jun 21, 2019 Β· 3 min read
Photo by Yancy Min on Unsplash

Clone repo with submodules included

git clone <url> --recursive

Create a submodule in a currently existing repo

git submodule add <url> <path>
git submodule update --init # Adding --recursive here will also update the submodule's submodule if it exists
git commit -m 'Added new submodule <name> at <path>'

If you want to update the path of the submodule (i.e. where the submodule will be stored on your local clone use

git submodule init
git mv oldpath/submodule newpathsubmodule
git submodule update

Please note this will change the entry in the .gitmodule file and you may not want to commit it and most of the time you will only be using git submodule update --init since it will be more consistent with the SCM

Check Submodules status

$ git submodule status
03608115df2071fff4eaaff1605768c275e5f81f bats (v0.4.0-6-g0360811)
9f88b4207da750093baabc4e3f41bf68f0dd3630 t/test_helper/bats-assert (v0.2.0-5-g9f88b42)
d0a131831c487a1f1141e76d3ab386c89642cdff t/test_helper/bats-support (v0.2.0)

Git submodules are actually using the commit rev of another repository and you will need to push these changes to your main repo if you want to updgrade them.

These are proven when checking out the plumbing of the rev which points to the submodule

$ git log bats
commit aa69c87bd96cb6aa0d586b871cfdd4da3abe0d3e
Author: <ancd@daklfma.net>
Date: Tue Sep 13 23:47:58 2016 +0900
Set up basic BATS test framework$ git cat-file -p aa69
tree b6e54e3e4a1e6aeae3a46d1c296a08dbd2bfd10a
parent e7134d506995dce59a14df8dd8d49a7a2e844a8d
author <ancd@daklfma.net> 1473778078 +0900
committer <ancd@daklfma.net>1473783135 +0900
$ git cat-file -p b6e54
100644 blob 82520ca123af9986966f282a109093cf39780722 .gitignore
100644 blob c1ddd1345dfd5b028dd16d55ae5f8aed286a019a .gitmodules
100644 blob b3d51add840a46d2590a3809905f0ebb980471f9 README.md
100755 blob 067db410b175787f5621b7737552e5e0558c7a3a Test
160000 commit 03608115df2071fff4eaaff1605768c275e5f81f bats ### Commit from another repository ###
040000 tree cc240386f9cc2546ec383b9d7afc7f432bf70f69 t

Pull a submodule after cloning a repository

# Your repository will have .gitmodules file
cd ~/repository
git submodule update --init # Adding --recursive here will also update the submodule's submodule if it exists

Update the repository url on .git/config from .gitmodules also

git submodule sync # Adding --recursive here will also update the submodule's submodule  if it exists

Checkout a specific branch on submodule

By default your submodule will check out the specific rev of a repository during the time of its commit to the main repository. If you want to use a branch in the submodule (for example stable branches) you will have to add branch on .gitmodules file and use

git submodule update --remote

If you didn’t specify any branches and used --remote it will automatically fetch master branch. If you are developing the submodule as well you can use either --merge or --rebase as convenience

[submodule "bats"]
branch = double-brackets
path = newbats/bats
url = https://github.com/sstephenson/bats.git
[submodule "t/test_helper/bats-assert"]
path = t/test_helper/bats-assert
url = https://github.com/ztombol/bats-assert
[submodule "t/test_helper/bats-support"]
path = t/test_helper/bats-support
url = https://github.com/ztombol/bats-support

Developing In Submodule

You can use a special push if you want to update your submodule from your main repo

$ git push --recurse-submodules=check
The following submodule paths contain changes that can
not be found on any remote:
DbConnector
Please try git push --recurse-submodules=on-demandor cd to the path and use git pushto push them to a remote.$ git push --recurse-submodules=on-demand
Pushing submodule 'DbConnector'
Counting objects: 9, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (8/8), done.
Writing objects: 100% (9/9), 917 bytes | 0 bytes/s, done.
Total 9 (delta 3), reused 0 (delta 0)
To https://github.com/chaconinc/DbConnector
c75e92a..82d2ad3 stable -> stable
Counting objects: 2, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 266 bytes | 0 bytes/s, done.
Total 2 (delta 1), reused 0 (delta 0)
To https://github.com/chaconinc/MainProject
3d6d338..9a377d1 master -> master

Also you can use a foreach comamand

$ git submodule foreach 'git stash'
Entering 'CryptoLibrary'
No local changes to save
Entering 'DbConnector'
Saved working directory and index state WIP on stable: 82d2ad3 Merge from origin/stable
HEAD is now at 82d2ad3 Merge from origin/stable

Finally you can use these alias to improve your workflow

$ git config alias.sdiff '!'"git diff && git submodule foreach 'git diff'"
$ git config alias.spush 'push --recurse-submodules=on-demand'
$ git config alias.supdate 'submodule update --remote --m

Faun

The Must-Read Publication for Aspiring Developers & DevOps Enthusiasts. Medium’s largest DevOps publication.

Kenichi Shibata

Written by

Git Ninja! Linux Nerd. Javascript evangelist. AWS Architect. Software engineer. Kubernetes Mentor and Architect

Faun

Faun

The Must-Read Publication for Aspiring Developers & DevOps Enthusiasts. Medium’s largest DevOps publication.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium β€” and support writers while you’re at it. Just $5/month. Upgrade