Table of Contents
13 Git Submodules
This page provides a quick overview to git submodules. Please refer to more in-depth documentation:
-
Command line options explained: https://git-scm.com/docs/git-submodule
Git submodule is an advanced feature of git that allows embedding a git repository inside another git repository. This is useful in some situations like:
-
Directly linking to an external library (this also allows for local corrections, if you don't have upstream rights)
-
Having several copies of the same code in one repository (e.g. duplication of code for windows and real-time systems, so they don't block each other during development)
The submodule knows nothing about the parent repository, so you may treat it like a regular git repository. The parent repository basically ignores all changes made inside a submodule path. If updates are made in a submodule, the new commit hash is noticed by the parent repository and available for stating.
Information about a submodule are kept in two places:
-
.gitmodules file in the root folder of parent repository contains relative paths to submodules as well as URL, branch, etc.
-
git saves the actual commit hash, which was last checked out, internally. Every time you update a submodule, the submodule relative path appears in changes to be staged; this information appears to be attached to the submodule directory, but it is actually stored somewhere else and just displayed as the submodule path by git
Working with submodules
Changing the repo URL
1. Modify the URL value in the .gitmodules
file
2. Commit the .gitmodules
file to Git
3. Force submodules to resynchronize with the modified file using the following command in the folder with the modified .gitmodules
file (not necessarily the repository root if its submodules contain other nested submodules):
git submodule sync
4. Update all modules from the now correct remote URL using the following command in the repository root (because it is called recursively on all submodules, even nested ones):
git submodule update --init --recursive --remote
Removing submodules
Read up on git rm
at https://git-scm.com/docs/git-rm.
Taken from GitHub Gist:
-
Delete the relevant section from the .gitmodules file.
-
Stage the .gitmodules changes git add .gitmodules
-
Delete the relevant section from .git/config.
-
Run git rm –cached path_to_submodule (no trailing slash).
-
Run rm -rf .git/modules/path_to_submodule (no trailing slash).
-
Commit git commit -m “Removed submodule ”
-
Delete the now untracked submodule files rm -rf path_to_submodule
Taken from Stackoverflow:
-
git rm <path-to-submodule>
-
rm -rf .git/modules/<path-to-submodule>
-
git config –remove-section submodule.<path-to-submodule>
-
commit
Pitfalls and Caveats
Submodule folder is empty or doesn't exist
This happens for example when you check out a repository without the submodules. To check them out afterwards you can use the following command:
git submodule update --init --remote --recursive
Detached head
The default behaviour of a submodule when checked out is to be in a detached head state. In this state, commits are hard to retrieve. Make sure to switch to an actual branch before attemping to make (non-local) changes.
Permission denied (publickey)
See GitLab FAQ.