====== 13 Git Submodules ====== This page provides a quick overview to git submodules. Please refer to more in-depth documentation: * Tutorial: [[https://git-scm.com/book/de/v1/Git-Tools-Submodule]] * 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 [[https://gist.github.com/myusuf3/7f645819ded92bda6677|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 [[https://stackoverflow.com/questions/1260748/how-do-i-remove-a-submodule/1260982#1260982|Stackoverflow]]: * git rm * rm -rf .git/modules/ * git config --remove-section submodule. * commit [[https://riptutorial.com/git/example/2652/removing-a-submodule|Alternative]] ---- ===== 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 [[kb:scc:gitlab:faq#cloning_of_git_submodules_fails_ci|GitLab FAQ]]. ---- ===== GitLab CI ===== See [[code:commercial:rat:install:configuration-gitlab|RAT: Config - GitLab]]