Need for submodule
- It often happens that while working on one project, you need to use another project from within it.
- A library that a third party developed or
- A library you’re developing separately and using in multiple parent projects
- One needs to treat the two projects as separate yet still be able to use one from within the other.
What Git has to offer
- Submodules allow you to keep a Git repository as a subdirectory of another Git repository.
- This lets you clone another repository into your project and keep your commits separate.
- Submodules maintain their own identity;
- The submodule support just stores the submodule repository location and commit ID, so other developers who clone the superproject can easily clone all the submodules at the same revision.
Creating a github submodule
1. The steps are the same as creating a repository: cd into project1 repository ( lets assume its under test organization.
$ git init
$ echo "Initial commit" > Readme.txt
$ git add Readme.txt
$ git commit -m "Initial commit, public module $mod"
$ git clone --bare . ~/subtut/public/$mod.git
In case you have already committed to a remote repository use
- $ git remote set-url https://github.com/test/project1.git
- $ git push origin master
OR
Add a new remote repository with github location
$ git remote add origin https://github.com/test/project1.git
$ git config branch.master.remote origin
$ git config branch.master.merge refs/heads/master
$ git push -u origin master
2. If in case the submodules were part of a parent repository as subfolders, you need to git rm those folders in order to add the submodules as git's submodules
$ git rm sudmodule or git rm subfolder
3. Now add the git submodule into parent as
$ git clone https://github.com/test/parent.git
$ cd parent
$ git pull origin master
$ ls
$ mkdir library/project1 && cd library/project1
$ git submodule add https://github.com/test/project1.git
The "git submodule add" command does a couple of things:
- It clones the submodule under the current directory and by default checks out the master branch.
- It adds the submodule's clone path to the ".gitmodules" file and adds this file to the index, ready to be committed.
- It adds the submodule's current commit ID to the index, ready to be committed.
4. Checkout .gitmodules file to check if the repository is added to the index and if the current commit ID of the submodule is added to the index.
$ cat .gitmodules
[submodule "game/guess_number"]
path = library/project1
url = https://github.com/test/project1.git
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: .gitmodules
# new file: library/project1
5. Commit the parent project and publish it:
$ cd ~/parent
$ git commit -m "Add submodules project1"
Created commit fc7c350: Add submodules a, b, c, d.
5 files changed, 16 insertions(+), 0 deletions(-)
create mode 100644 .gitmodules
create mode 160000 a
create mode 160000 b
create mode 160000 c
create mode 160000 d
$ git push
$ git submodule init
Things To Remember
1. In case you are pulling parent into current repository, you will need to perform 2 simple steps to get the submodules updates and filled
First run "git submodule init" to add the submodule repository URLs to .git/config:
$ git submodule init
$ git config -l
...
submodule.a.url=/home/moses/subtut/public/a.git
Now use "git submodule update" to clone the repositories and check out the commits specified in the superproject.
$ git submodule update
2. One major difference between "submodule update" and "submodule add" is that "update" checks out a specific commit, rather than the tip of a branch. It's like checking out a tag: the head is detached, so you're not working on a branch.
$ git branch
* (no branch)
master
3. If you want to make a change within a submodule, you should first check out a branch, make your changes, publish the change within the submodule, and then update the Parent project to reference the new commit:
$ git branch
* (no branch)
master
$ git checkout master
$ echo "adding a line again" >> README.txt
$ git commit -a -m "Updated the submodule from within the ParentProject."
$ git push
$ cd ..
$ git add README.txt # There is a gotcha here. Read about it below.
$ git commit -m "Updated submodule project1."
$ git show
...
diff --git a/README.txt b/README.txt
index d266b98..261dfac 160000
--- a/README
+++ b/README
@@ -1 +1 @@
-Subproject commit d266b9873ad50488163457f025db7cdd9683d88b
+Subproject commit 261dfac35cb99d380eb966e102c1197139f7fa24
$ git submodule summary HEAD^
* a d266b98...261dfac (1):
> Updated the submodule from within the ParentProject.
$ git push
4. To remove a submodule you need to:
- Delete the relevant line from the .gitmodules file.
- Delete the relevant section from .git/config.
- Run git rm --cached path_to_submodule (no trailing slash).
- Commit the superproject.
- Delete the now untracked submodule files.
references : http://git-scm.com/book/en/Git-Tools-Submodules