Use Git Submodule to Manage Project Dependencies

It’s common to include a third-party git repo in your own git project. Sometime I want to make some local changes to the third-party repo without pushing to the origin master and also want to keep other parts in sync with the third-party’s master. This article provides one way to achieve this by using git submodule.

I’m using adding a theme to hexo as an example, I have a git repo of a hexo project:

gen@do:~/hexo$ tree -L 1 -a
. <my parent git repo>
├── _config.yml
├── db.json
├── .git
├── .gitignore
├── node_modules
├── package.json
├── public
├── scaffolds
├── source
└── themes
    └── <theme's git repo put here>

I want to add this theme(https://github.com/heroicyang/hexo-theme-modernist) by putting its git repo into the themes directory.

Step 1: Fork the theme’s repo

It is as easy as going to https://github.com/heroicyang/hexo-theme-modernist and click the fork button. Now I have my fork of the repo at https://github.com/genliu/hexo-theme-modernist.git

Step 2: Add submodule

gen@do:~/hexo$ git submodule add https://github.com/genliu/hexo-theme-modernist.git themes/modernist

This works like git clone, now the themes dir look like:

gen@do:~/hexo$ tree themes/ -L 2
themes/
└── modernist
    ├── _config.yml
    ├── languages
    ├── layout
    ├── LICENSE
    ├── README.md
    └── source

Also a .gitmodule file is created to trace the submodule:

gen@do:~/hexo$ cat .gitmodules
[submodule "themes/modernist2"]
    path = themes/modernist2
    url = https://github.com/genliu/hexo-theme-modernist.git

Step 3: Add the original repo as upstream

gen@do:~/hexo/themes/modernist2$ git remote add upstream https://github.com/heroicyang/hexo-theme-modernist.git
gen@do:~/hexo/themes/modernist2$ git remote -v
origin    https://github.com/genliu/hexo-theme-modernist.git (fetch)
origin    https://github.com/genliu/hexo-theme-modernist.git (push)
upstream    https://github.com/heroicyang/hexo-theme-modernist.git (fetch)
upstream    https://github.com/heroicyang/hexo-theme-modernist.git (push)

Step 4: Make local changes to the theme(submodule) and commit

Step 5: Sync original repo

gen@do:~/hexo/themes/modernist2$ git fetch upstream
gen@do:~/hexo/themes/modernist2$ git checkout master
gen@do:~/hexo/themes/modernist2$ git merge upstream/master

Others

Initialize submodule in newly cloned repo

When I clone the parent(hexo) repo somewhere else, the submodule(themes/modernist) won’t automatically cloned. I only get a empty dir of themes/modernist. Need to initialze it:

gen@do:~/hexo2 $ git submodule init
gen@do:~/hexo2 $ git submodule update

Delete submodule

gen@do:~/hexo2 $ git submodule deinit themes/modernist
gen@do:~/hexo2 $ git rm themes/modernist

References

  1. http://git-scm.com/book/en/Git-Tools-Submodules
  2. https://help.github.com/articles/fork-a-repo
  3. https://help.github.com/articles/syncing-a-fork
  4. http://stackoverflow.com/questions/1260748/how-do-i-remove-a-git-submodule