Basetta's Website

Rants and Raves

Extract a Directory From a Git Branch/Repository Preserving the History

| Comments

At work we wanted to extract from a branch a subdirectory containing a specific feature that had to be used from everyone in the team.

Just for sake of example, let’s define the terms of our problem. Our repository (MAIN) structure looks like:

1
2
3
4
5
MAIN/
        Library/
            libA/
            libB/
            libC/

Our goal is to extract the libA contained in the branch FTR-B in its own branch called FTR-A.

If you are not interested in preserving the history the task is quite easy. Git checkout is our friend in this case.

1
2
3
4
5
$ git checkout master
$ git checkout -b FTR-A
$ git checkout FTR-B Library/libA
$ git commit -a -m "Extract libA"
$ git push

More complicated is the case in which preserving the history is a matter of importance. For God’s sake git has a powerful command git filter-branch. The following are my notes and observations, for pleasing my poor memory.

  • Clone the local repository into a temporary repository DIRTY.
1
2
3
$ git clone ~/MAIN/ ~/DIRTY/
$ cd DIRTY
$ git checkout FTR-B
  • Remove everything except the desired subdirectory ( libA ).
1
$ git filter-branch --prune-empty --tree-filter 'rm -rf Library/libB Library/libC'

Basically, Git filter-branch executes a command on each commit in a specific branch. Instead of the option tree-filter you could have used subdirectory-filter that removes everything except the desired directory moving it up to the root project. I will explain it better in another post.

  • Clean all the cruft
1
$ git gc --aggressive
  • Merge the new feature in its own branch FTR-A.
1
2
3
4
5
6
7
8
$ cd ~/MAIN
$ git remote add dirty ~/DIRTY
$ git fetch dirty
$ git branch dirty remotes/tools/FTR-B
$ git checkout master
$ git checkout -b FTR-A
$ git merge dirty
$ git remote rm dirty
  • Create a pull request

How to Fetch Upstream Changes in Git Easily

| Comments

It is quite common to update your git fork repository with the upstream changes.

Here it is the workflow I use to keep synchronize my branch with Octopress.

  • First of all, we should configure the remotes.
1
$ git remote add upstream git://github.com/imathis/octopress.git
  • Check the remotes
1
$ git remote
  • Merge/Rebase the changes
1
2
3
$ git fetch origin -v
$ git fetch upstream -v
$ git merge upstream/master

If you prefere you can create an alias in your .gitconfig.

1
2
[alias]
  pull_upstream = !"git fetch origin -v; git fetch upstream -v; git merge upstream/master"

Now git pull_upstream will fetch the changes of both remotes, and the merge in the upstream changes.

Back Online

| Comments

It has been nearly four years since I last posted. Quite a lot. Anyhow, now I am back online thanks to Octopress and Github pages.

I’ll have more to do:

  • write a catch up post
  • importing the old posts parked here after my previous Django blog abandoned me.
  • personalized the Octopress default template.