Skip to main content
Chapter 9 of 61 · 6 sections · Page 56

Git: Submodules

Clone, initialize, update, move, and remove embedded Git repositories and branch tracking.

Original chapter reference: Chapter 9: Submodules. The command options and documentation recipes below are fully transcribed from Git Notes for Professionals.

Section 9.1: Cloning a Git repository having submodules

When you clone a repository that uses submodules, you'll need to initialize and update them.

Source example · PDF page 56
$ git clone --recursive https://github.com/username/repo.git

This will clone the referenced submodules and place them in the appropriate folders (including submodules within submodules). This is equivalent to running git submodule update --init --recursive immediately after the clone is finished.

Section 9.2: Updating a Submodule

A submodule references a specific commit in another repository. To check out the exact state that is referenced for all submodules, run

Source example · PDF page 56
git submodule update --recursive

Sometimes instead of using the state that is referenced you want to update to your local checkout to the latest state of that submodule on a remote. To check out all submodules to the latest state on the remote with a single command, you can use

Source example · PDF page 56
git submodule foreach git pull <remote> <branch>

or use the default git pull arguments

Source example · PDF page 56
git submodule foreach git pull

Note that this will just update your local working copy. Running git status will list the submodule directory as dirty if it changed because of this command. To update your repository to reference the new state instead, you have to commit the changes:

Source example · PDF page 56
git add <submodule_directory>
git commit

There might be some changes you have that can have merge conflict if you use git pull so you can use git pull --rebase to rewind your changes to top, most of the time it decreases the chances of conflict. Also it pulls all the branches to local.

Source example · PDF page 56
git submodule foreach git pull --rebase

To checkout the latest state of a specific submodule, you can use :

Source example · PDF page 56
git submodule update --remote <submodule_directory>

Section 9.3: Adding a submodule

You can include another Git repository as a folder within your project, tracked by Git:

Source example · PDF page 56
$ git submodule add https://github.com/jquery/jquery.git

You should add and commit the new .gitmodules file; this tells Git what submodules should be cloned when git submodule update is run.

Section 9.4: Setting a submodule to follow a branch

A submodule is always checked out at a specific commit SHA1 (the "gitlink", special entry in the index of the parent repo)

But one can request to update that submodule to the latest commit of a branch of the submodule remote repo.

Rather than going in each submodule, doing a git checkout abranch --track origin/abranch, git pull, you can simply do (from the parent repo) a:

Source example · PDF page 57
git submodule update --remote --recursive

Since the SHA1 of the submodule would change, you would still need to follow that with:

Source example · PDF page 57
git add .
git commit -m "update submodules"

That supposes the submodules were:

either added with a branch to follow:

Source example · PDF page 57
        git submodule -b abranch -- /url/of/submodule/repo

or configured (for an existing submodule) to follow a branch:

Source example · PDF page 57
        cd /path/to/parent/repo
        git config -f .gitmodules submodule.asubmodule.branch abranch

Section 9.5: Moving a submodule

Source example · PDF page 57
Version > 1.8

Run:

$ git mv /path/to/module new/path/to/module

Source example · PDF page 57
Version ≤ 1.8

1. Edit .gitmodules and change the path of the submodule appropriately, and put it in the index with git add

Source example · PDF page 57
     .gitmodules.

2. If needed, create the parent directory of the new location of the submodule (mkdir -p /path/to).

3. Move all content from the old to the new directory (mv -vi /path/to/module new/path/to/submodule).

4. Make sure Git tracks this directory (git add /path/to).

5. Remove the old directory with git rm --cached /path/to/module.

6. Move the directory .git/modules//path/to/module with all its content to .git/modules//path/to/module.

7. Edit the .git/modules//path/to/config file, make sure that worktree item points to the new locations, so in this example it should be worktree = ../../../../..//path/to/module. Typically there should be two more .. then directories in the direct path in that place. . Edit the file /path/to/module/.git, make sure that the path in it points to the correct new location inside the main project .git folder, so in this example gitdir: ../../../.git/modules//path/to/module.

git status output looks like this afterwards:

Source example · PDF page 58
       # On branch master
       # Changes to be committed:
       #   (use "git reset HEAD <file>..." to unstage)
       #
       #       modified:   .gitmodules
       #       renamed:    old/path/to/submodule -> new/path/to/submodule
       #

8. Finally, commit the changes.

This example from Stack Overflow, by Axel Beckert

Section 9.6: Removing a submodule

Source example · PDF page 58
Version > 1.8

You can remove a submodule (e.g. the_submodule) by calling:

Source example · PDF page 58
$ git submodule deinit the_submodule
$ git rm the_submodule

git submodule deinit the_submodule deletes the_submodules' entry from .git/config. This excludes the_submodule from git submodule update, git submodule sync and git submodule foreach calls and deletes its local content (source). Also, this will not be shown as change in your parent repository. git submodule init and git submodule update will restore the submodule, again without commitable changes in your parent repository.

git rm the_submodule will remove the submodule from the work tree. The files will be gone as well as the submodules' entry in the .gitmodules file (source). If only git rm the_submodule (without prior git submodule deinit the_submodule is run, however, the submodules' entry in your .git/config file will remain.

Source example · PDF page 58
Version < 1.8

Taken from here:

1. Delete the relevant section from the .gitmodules file.

2. Stage the .gitmodules changes git add .gitmodules

3. Delete the relevant section from .git/config.

4. Run git rm --cached path_to_submodule (no trailing slash).

5. Run rm -rf .git/modules/path_to_submodule

6. Commit git commit -m "Removed submodule <name>"

7. Delete the now untracked submodule files

Source example · PDF page 58
  8. rm -rf path_to_submodule
Buy me a coffee
Daily Practice
0/0