Git: how to work with submodules

Updated . Posted . Visible to the public.

Sometimes you might need to nest a git-project inside another git-project. The right strategy is to use submodules in this case.

How git submodules work

  • Each submodule is a own git repository
  • Once you commit changes in a submodule, the parent repository can link the new sha as its reference
  • You need to take care manually that your git submodules are up-to-date and changes in the submodules are linked in the parent repository

Add a submodule

Here is how you add a nested project inside your parent project

$ git submodule add <nested-repository-url>

git status will now show you the following:

new file:   .gitmodules
new file:   nested_project

nested_project will point to the specific sha of the nested project. It will never add the files inside the submodule.

Clone a project with submodule

New team members can check out the the parent project and the nested project with one command:

git clone --recursive <parent-repository-url>

If you forgot to add the --recursive-flag, you have to do the following to pull the code for the submodule:

git submodule init
git submodule update

Update a submodule and reference it to the parent-repository

cd ~/Project/parent-repository/submodules/nested_project

touch example.txt
git add .
git commit -m 'New file'
git push

cd ~/Project/parent-repository
git add submodules/nested_project
git commit -m 'Use new version of nested_project'
git push

Checkout the parent-repository and all its submodules with the correct referenced shas

cd ~/Project/parent-repository
git submodule update

Update the parent-repository module to the most current version of the submodules

In general submodules are in a detached head-state. Nevertheless you can update the reference for all to master.

git submodule foreach --recursive git fetch
git submodule foreach --recursive git checkout master

You now will see a message like:

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   ~/Project/parent-repository/submodules/nested_project (new commits)

Submodules changed but not updated

no changes added to commit (use "git add" and/or "git commit -a")

Reference the new sha in the the parent-repository and push:

git add submodules/nested_project
git commit -m 'Update the submodules`
git push

Advanced configuration

It is helpful to set the global git config git config status.submodulesummary 1. This will add a short summary of the commits in the git submodules.

Example:

$ git config status.submodulesummary 1

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

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

	modified:   .gitmodules
	modified:   DbConnector (new commits)

Submodules changed but not updated:

* DbConnector c3f01dc...c87d55d (4):
  > catch non-null terminated lines
Profile picture of Daniel Straßner
Daniel Straßner
Last edit
Daniel Straßner
License
Source code in this card is licensed under the MIT License.
Posted by Daniel Straßner to makandra dev (2016-09-07 11:27)