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
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)