This tip will be useless for most of all. But if you are involved in porting of something to something better (or at least something you get paid for), for example porting project from LESS to SASS. Well you don’t need anything special for such purpose, but the problem comes out when you want to have exact copy of original repo (with different branches), but with ported sources.
The best explanation of a problem is my port of Twitter’s Bootstrap
CSS framework. As you can see, I’m trying to make my bootstrap.scss exactly
match original sources, but written in SASS. Also I want to have two branches:
2.0-wip and keep work on both within same repo, just like
original repo does.
To track changes in original repo more easily, I have decided to add it as a submodule to my repo. And created branches (I wanted to work on) with same names as original ones. So it was something like this:
ixti@msi:~/demo$ git submodule add git://github.com/twitter/bootstrap.git ./src Cloning into src... remote: Counting objects: 4664, done. remote: Compressing objects: 100% (1728/1728), done. remote: Total 4664 (delta 3046), reused 4408 (delta 2837) Receiving objects: 100% (4664/4664), 1.20 MiB | 534 KiB/s, done. Resolving deltas: 100% (3046/3046), done. ixti@msi:~/demo$ git commit -m 'Added original repo as submodule' [master 5871d81] Added original repo as submodule 2 files changed, 4 insertions(+), 0 deletions(-) create mode 100644 .gitmodules create mode 160000 src ixti@msi:~/demo$ cd src && git branch -a && cd .. * master remotes/origin/2.0-wip remotes/origin/HEAD -> origin/master remotes/origin/dev remotes/origin/gh-pages remotes/origin/kasperp-dropdown-btn-dev remotes/origin/master ixti@msi:~/demo$ git checkout -b 2.0-wip Switched to a new branch '2.0-wip' ixti@msi:~/demo$ cd src && git checkout 2.0-wip && cd .. Branch 2.0-wip set up to track remote branch 2.0-wip from origin. Switched to a new branch '2.0-wip' ixti@msi:~/demo$ git commit -am 'Initial start of 2.0-wip branch' [2.0-wip 659720a] Initial start of 2.0-wip branch 1 files changed, 1 insertions(+), 1 deletions(-)
Everything is cool, except one annoying thing -
src does not tracks your
checkouts in main repo, so when you will checkout to the master branch in your
repo, it will tell you that
src is modified, so you’ll need to manually check
ixti@msi:~/demo$ git checkout master M src Switched to branch 'master' ixti@msi:~/demo$ cd src && git checkout master && cd .. Switched to branch 'master' ixti@msi:~/demo$ git status # On branch master nothing to commit (working directory clean)
Fortunately we can automatize this pain with this simple
#!/bin/sh #file: .git/hooks/post-checkout # Get active branch name after checkout BRANCH=$(git branch | grep '^*' | cut -b 3-) # Silently exit when checked out on specific commit (no branch) if [ "x(no branch)" = "x$BRANCH" ] ; then exit 0; fi # Get into our submodule with original repo cd src # Silently exit when original repo has no similarly named branch git branch | grep "$BRANCH" -q || exit 0 # Checkout original repo to be on same branch as we are git checkout $BRANCH
In order to use it, just put it into your
(normally it will be
.git/hooks/ under root directory of your repo).
For more details on hooks, please
man githooks. Also you might find useful
reading ProGit and Git Book about hooks.