Tuesday, 7 October 2014

Git Subtree


In this article we will look at how to use  Git Subtree Tool to split a sub-directories of a project into separate project

Git Subtree

It often happens that while working on a project,you need to reference another project within it.It may be sources of a third party library or a that particular submodule needs to be treated as seperate project .

Subtrees allow subprojects to be included within a subdirectory of the main project, optionally including the subproject's entire history .

git subtree feature enables user to either Merge subtrees together or split repository into subtrees
Let us consider the repository OpenVision that can be found at www.github.com/pi19404/OpenVision
let us say we want to extract the directory ImgML/pyVision as a separate project.
First step is to clone  the OpenVision repository on local PC

git clone https://github.com/pi19404/openVision.git
Then create the new repository on the local PC
mkdir pyVision

cd pyVision
Initialize a empty git repository and associate it with remote repository on github
git init --bare 

git remote add origin https://github.com/pi19404/pyVision.git
git push -u origin master
now we have two independent repositories.
in the parent repository we run the git subtree split command to create a subtree
git subtree split --prefix ImgML/PyVision --annotate="(pyVision)" -b pyVision
Created branch 'pyVision'

now we create a remote repository

and now we push the subtree changes onto the remote repository using subtree push command
git subtree push --prefix=ImgML/PyVision pyVision master
git push using:  pyVision master
Username for 'https://github.com': pi19404
Password for 'https://pi19404@github.com': 
Counting objects: 43, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (43/43), done.
Writing objects:  25% (11/43), 21.11 MiB | 50.00 KiB/s    
Writing objects: 100% (43/43), 24.78 MiB | 26.00 KiB/s, done.
Total 43 (delta 18), reused 0 (delta 0)
remote: warning: GH001: Large files detected.
remote: warning: See http://git.io/iEPt8g for more information.
remote: warning: File MLP.pyvision1 is 54.42 MB; this is larger than GitHub's recommended maximum file size of 50 MB
To https://github.com/pi19404/pyVision
 * [new branch]      ae84838a2975d3a51efbab7f7c0fbcb94783c056 -> master

now we commit the changes in pyVision repository to remote github.we can see all the files committed in the parent repository along with the github history present in the new repository

pi19404  authored 

now there can be two cases of updating the project in the parent or separated repository 
To avoid any issues,we remove the subdirectory and create is again the parent directory

git rm ImgML/PyVision

git subtree add --prefix=ImgML/PyVision pyVision master

commit 6c22aa8f1c11b201ff03f057963d5b4063c85457
Merge: 7676342 6ce46a5
Author: pi19404 
Date:   Tue Oct 7 01:58:43 2014 +0530

    Add 'ImgML/PyVision/' from commit '6ce46a56b2052fc549f0db3e6e52f56083fb0e64'
    git-subtree-dir: ImgML/PyVision
    git-subtree-mainline: 7676342aa84a7b4d8bfffc655d6f0ed9af1a7eda
    git-subtree-split: 6ce46a56b2052fc549f0db3e6e52f56083fb0e64

Changes in parent Directory

The above git log comments are essential when pulling commits from subdiretory remote repository

Changes in Parent Directory

Let us make some changes in the parent repository,remove the files test_parser.py,test_parser3.py,test_plot.pyt,t3.py,sgd.py,parsetab.py,m1.py,calclex.py,bac.py,LoadDatasets.pyb

 git commit -m "removing unwanted files" -a
[master 4156a4d] removing unwanted files

git push origin master

will commit if any changes to master branch,but the subdirectory branch remains unaffected.
To push changes to subdirectory branch we execute

git subtree push --prefix=ImgML/PyVision pyVision master

Changes in the subdirectory

Let us make some changes in the sub directory and we want the changes to reflect in the parent directory

we push multiple commits onto the remote subdirectory and merge them in parent directory and maintaining all the changes in remote as a single commit using the squash directive

  1.  authored 

we pull the changes from the parent directory
git subtree pull --prefix=ImgML/PyVision pyVision master --squash


you can find instructions on how to install git subtree from sources at link http://engineeredweb.com/blog/how-to-install-git-subtree/ since git subtree changes were introduced in git version 1.7.11 it may not be available in ubuntu repositories by default.
Else you can install latest version of git
sudo add-apt-repository ppa:git-core/ppa 
use synaptic ,update the sources by clicking on reload and install the latest version of git

git subtree sciript can be found at /usr/share/doc/git/contrib/subtree/git-subtree.sh