Using Git repositories inside other Git repositories
Git allows you to include other Git repositories called submodules into a repository. This allows you to track changes in several repositories via a central one. Submodules are Git repositories nested inside a parent Git repository at a specific path in the parent repository’s working directory. A submodule can be located anywhere in a parent Git repository’s working directory and is configured via a .gitmodules file located at the root of the parent repository. This file contains which paths are submodules and what URL should be used when cloning and fetching for that submodule. Submodule support includes support for adding, updating, synchronizing, and cloning submodules.
Git allows you to commit, pull and push to these repositories independently.
Submodules allow you to keep projects in separate repositories but still be able to reference them as folders in the working directory of other repositories.
Working with repositories that contain submodules
- Cloning a repository that contains submodules
|
|
If you already have cloned a repository and now want to load it’s submodules you have to use submodule update.
|
|
- Downloading multiple submodules at once
Since a repository can include many submodules, downloading them all sequentially can take much time. For this reason clone and submodule update command support the –jobs parameter to fetch multiple submodules at the same time.
|
|
- Pulling with submodules
Once you have set up the submodules you can update the repository with fetch/pull like you would normally do. To pull everything including the submodules, use the –recurse-submodules and the –remote parameter in the git pull command.
|
|
- Executing a command on every submodule
Git provides a command that lets us execute an arbitrary shell command on every submodule. To allow execution in nested subprojects the –recursive parameter is supported. For our example we assume that we want to reset all submodules.
|
|
Creating repositories with submodules
- Adding a submodule to a Git repository and tracking a branch
If you add a submodule, you can specify which branch should be tracked via the -b parameter of the submodule add command. The git submodule init command creates the local configuration file for the submodules, if this configuration does not exist.
|
|
- adds a new submodule to an existing Git repository and defines that the master branch should be tracked
- initialize submodule configuration
If you track branches in your submodules, you can update them via the –remote parameter of the git submodule update command. This pulls in new commits into the main repository and its submodules. It also changes the working directories of the submodules to the commit of the tracked branch.
|
|
- Adding a submodule and tracking commits Alternatively to the tracking of a branch, you can also control which commit of the submodule should be used. In this case the Git parent repository tracks the commit that should be checked out in each configured submodule. Performing a submodule update checks out that specific revision in the submodule’s Git repository. You commonly perform this task after you pull a change in the parent repository that updates the revision checked out in the submodule. You would then fetch the latest changes in the submodule’s Git repository and perform a submodule update to check out the current revision referenced in the parent repository. Performing a submodule update is also useful when you want to restore your submodule’s repository to the current commit tracked by the parent repository. This is common when you are experimenting with different checked out branches or tags in the submodule and you want to restore it back to the commit tracked by the parent repository. You can also change the commit that is checked out in each submodule by performing a checkout in the submodule repository and then committing the change in the parent repository.
You add a submodule to a Git repository via the git submodule add command.
|
|
- adds a submodule to the existing Git repository
- initialize submodule configuration
- Updating which commit you are tracking
The relevant state for the submodules are defined by the main repository. If you commit in your main repository, the state of the submodule is also defined by this commit.
The git submodule update command sets the Git repository of the submodule to that particular commit. The submodule repository tracks its own content which is nested into the main repository. The main repository refers to a commit of the nested submodule repository.
Use the git submodule update command to set the submodules to the commit specified by the main repository. This means that if you pull in new changes into the submodules, you need to create a new commit in your main repository in order to track the updates of the nested submodules.
The following example shows how to update a submodule to its latest commit in its master branch.
Another developer can get the update by pulling in the changes and running the submodules update command.
|
|
With this setup you need to create a new commit in the master repository, to use a new state in the submodule. You need to repeat this procedure every time you want to use another state in one of the submodules.
Delete a submodule from a repository
To remove a submodule you need to:
- Delete the relevant section from the .gitmodules file.
- Stage the .gitmodules changes:
|
|
- Delete the relevant section from .git/config.
- Remove the submodule files from the working tree and index:
|
|
- Remove the submodule’s .git directory:
|
|
- Commit the changes:
|
|
- Delete the now untracked submodule files:
|
|