How to work with Git Submodules
Overview
- Adding an existing git repository as a submodule
- Cloning a project with a submodule in it
- git clone
- after git clone
- git clone using the shorthand
- State of submodule
- .gitmodules
- the directory
- Managing the local repo containing a submodule
- fetching update for all submodules at once
- git status
- git pull
- merge changes from remote into local
- rebase with remote into the local
- git push
- fail push if submodule has commits
- push submodule first
- References
Adding an existing git repository as a submodule
To add an existing git repository as a submodule, you add it as follows:
git submodule add http://github.com/bishtbytes/git-submodule-repo
Cloning a project with a submodule in it
git clone
When you clone a project as follows, only the directories containing submodules will be added but not their content:
git clone http://github.com/bishtbytes/git-mainproject-repo
after git clone
To clone a project containing submodule, you have to run the following two command after the git clone:
git submodule init
git submodule update
Shorthand for running the above command using one line is:
git submodule update --init
If you have nested submodules, then you will have to use:
git submodule update --init --recursive
git clone using the shorthand
Instead of using the above three commands, you could directly use the following while cloning:
git clone --recurse-submodules http://github.com/bishtbytes/git-mainproject-repo
The above command will automatically initialize and update the submodule in the repository including nested submodules if any.
State of submodule
.gitmodules
.gitmodules file will point where the submodule repo is.
also which local repository to use to clone the submodule into.
the directory
The submodule directory acts only as a pointer to a commit for the main project.
To point to a certain commit of the submodule repo in the main project, you need to update the commit pointer.
As time passees by you repo will be behind the remote submodule repo. You need to pull the latest from that and commit to this new change in the main project.
Managing the local repo containing a submodule
To get the latest from the remote into your local, you have to run the following:
cd git-submodule-repo
git fetch
git merge
Now your local submodule will have a new changes available in the submodule repo.
fetching update for all submodules at once
Git can go into your submodules and fetch and update all of them at once using:
git submodule update --remote
git status
If you run git status
you wont see details about changes in submodule. Only you would see (new commits)
against the submodule directory.
To get more details, you need to update the git config as follows:
git config status.submodulesummary 1
After this config update, you will see details about changes in your submodule when you run:
git status
git pull
git pull
by default fetches submodules changes. It does not update the submodules.
To update the submodule, we have fallback to what we do to update a submodule:
git submodule update
If there could be newly added submodule, you have to do this:
git submodule update --init
If there could be newly added submodule and nested submodules to update, do this:
git submodule update --init --remote
merge changes from remote into local
To merge changes from remote into local, you do this:
git submodule update --remote --merge
rebase with remote into the local
If there is some local changes in our submodule and we want to rebase with the remote, we do this:
git submodule update --remote --rebase
git push
You can push the changes in the main project without pushing the changes in submodule using:
git push
fail push if submodule has commits
To prevent push in the main project from succeeding when there are changes (committed in local but havent been pushed) in the submodule, instead of doing git push
you run the following:
git push --recurse-submodules=check
push submodule first
To push the submodule commits first and then the main project commits, you do the following:
git push --recurse-submodules=on-demand
If submodule push fails, main project fails too.