Firstly, you need to know what a commit is and how it looks like. From Wikipedia:
Every commit in the repository is different, has a unique identification (or simply a hash). You can get this id with command
However, every commit has a long id or short
git log --pretty=format:%h)
So with every command
you create a unique snapshot of the current code in your repository. And this is important. You probably know that you can do
to another branch, but also you can check out to a specific commit. To do that, simply run
git checkout commit_hash
And from this point, you can create new branches, do commits and other commands which you normally do when you are on a branch.
What is a git submodule?
Git submodule is a normal repository with all the features that comes with git. And it’s very important to remember this.
How to add git submodule?
With a simple command
git submodule add [<options>] [<repository>]
It’s very similar to command
so you can add the repository by ssh or https, define specific folder etc. That command will create an empty directory and add proper options to file
Why is the directory empty? Because submodule wasn’t initialized.
To get the code from the submodule you need to run
git submodule update
It will download all files from the repository. Which branch? As it was said, It’s similar to the clone command, so you will have HEAD from the master branch. When you will push changes to the remote server, you will have a directory with submodule and hash of the last commit from the master. When you will click on it, it will redirect you to the submodule repository. What is most important, the parent repository is storing only the hash commit of the submodule repository.
How to make changes to the submodule?
If you will change some files on the submodule and you will run
you will see “modified content”, but you cannot add this to the stage. Why? Because parent repository sees, that something has changed, but the hash of the submodule hasn’t changed. You need to go to the submodule directory and create commit. It is important to push this commit to the server, without it, you will be the only person that has this commit on the local machine. After this push, nothing will change in the parent repository. Go back to it and run
You will see, that submodule has
At this moment you can add a submodule to the stage and create a new commit.
What is important?
You need to remember that changes made on the submodule don’t trigger changes in the parent repository. You need to push separately commits from both repositories. There is also the possibility to have submodule in the submodule. In that case, you can use
git submodule update
command. Also, after someone will clone your repository with submodules, they should use
git submodule update --init
to initialize and download submodule code.
To get familiar with git submodules, I’ve prepared some exercises, which can be done in 10 minutes:
- Create a repository (hereinafter referred to as REPO1), add some files, push them to the remote server (GitHub/Bitbucket).
- Create another repository (hereinafter referred to as REPO2), add some files, push them to the remote server (GitHub/Bitbucket).
- Add REPO2 as a submodule in REPO1 in src/common directory (all files from the REPO2 should be in src/common directory, not src/REPO2), push changes to the server.
- Clone REPO1 to another directory (hereinafter referred to as REPO1Copy), initialize submodules (hereinafter referred to as REPO2Copy).
- Modify the file in REPO2 on the new branch (repo2-test-branch), push changes to the server, create a new branch in REPO1 (repo1-test-branch), push changes to the server, create Pull Requests for both branches, check how they look like.
- Checkout to repo1-test-branch branch in REPO1Copy, pull changes from submodules.
- Modify the file in REPO1 in branch repo1-test-branch, push changes to the server.
- Checkout to the first commit in REPO2, commit changes in REPO1 and push changes to the server.
- In REPO1Copy pull changes from the server.
- Checkout to master branch in REPO1, update submodules.
- Merge repo1-test-branch to master branch (through Pull Request), pull changes from the remote master in REPO1 and REPO1Copy (observe, that you don’t need to merge repo2-test-branch to master branch, to have actual changes in the parent repository).
That’s it! Now you know how to share code between projects. Have fun with submodules.