Saturday, May 30, 2009

Tracking forks on Github

I have been using github for a few of my projects, and occasionally have forked another project so I can add my own changes.

Today I forked a project and made some changes, and then found another fork with some code I wanted.

The project is simple-navigation - a Rails plugin to create and manage multi-layered navigation.

After creating a fork on github, I cloned my new fork locally:

$ git clone git@github.com:rhulse/simple-navigation.git

I then added my own changes and committed them.

User edk has added some breadcrumb code that works in a similar way to some standalone code I use in my projects. I want to grab this code, have a look at the differences, and merge it in to my master branch.

The first step is adding edk's repository as a remote:

$ git remote add edk git://github.com/edk/simple-navigation.git

Step two is fetching any objects in that repository that I don't have in mine:

$ git fetch edk

The output from that command looks like this:

remote: Counting objects: 25, done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 17 (delta 12), reused 0 (delta 0)
Unpacking objects: 100% (17/17), done.
From git://github.com/edk/simple-navigation
* [new branch] gh-pages -> edk/gh-pages
* [new branch] master -> edk/master

It is then a simple matter to create a branch and put edk's master branch in it:

$ git checkout -b edk edk/master

The last step is to compare the changes between my master and the edk branch. At this stage it might be tempting to just type this:

$ git diff master edk

The problem is that while you'll see all the additions made by edk, you will also see changes made on the master branch as removals.

To see just edk's changes I used this command:

$ git diff master...edk

This does a diff from the most recent common ancestor. The resultant output contains only code made since the point at which edk started adding changes. (Hat tip to Scott Chacon who mentioned this in his Scotland on Rails git talk)

If I wanted to change any of the new code I could do it in the new edk branch, or make a third branch.

The last step is to merge the new code into my master branch. While on master:

$ git merge edk

When these changes are pushed back to github, the network display page will show the new activity and merges.

And before you ask, you can track as many remotes as you want.

1 comment:

tgoddard said...

Great hint there about the diff from common ancestor - I'd never come across that form. I can't count the number of times I've typed something along the lines of git diff `git merge-base $a $b`..$b to get the same effect. That sort of thing should be a lot easier now, thanks!

Tim Goddard