Mechanical Robot Fish

The Mixed-Up Thoughts of Michael Francis Booth

Checking Out an Open-source Git Project: The Right Way

(Paraphrased from Long Nguyen’s guide to checking out projects from GitHub – which is excellent, except that Long uses the name “long” for too many different things, making the code hard for mere mortals to read.)

Suppose you would like to work on the open-source Insoshi project. You have the URL of its official git repository:

git://github.com/insoshi/insoshi.git

You could simply clone this URL to your own machine:

$ git clone git://github.com/insoshi/insoshi.git

after which you could mess around with your local copy as much as you like. But it’s hard to share a local repository with your friends, or among several machines, so perhaps you’d rather create a private fork on a server somewhere. It’s easy to do this with a GitHub-hosted project like Insoshi – you get a GitHub account, then press GitHub’s “fork” button, and you rewarded with the URL for your own personal GitHub-hosted fork:

git@github.com:mechfish/insoshi.git

Now you could make a local clone of that remote fork:

$ git clone git@github.com:mechfish/insoshi.git

but there are disadvantages to that. One is that the local clone will have a different parent: its origin will be remote fork, while the remote fork’s origin is the official project repository. Ideally, you would want the two repositories to be interchangeable, so that you won’t get confused when comparing them, and so you can upload the local version to replace the remote version if it gets lost or corrupted.

You’d also like to be able to pull changes from the official repository directly into your local copy, then push them up to the remote fork, rather than having to pull every change forward through the chain: official -> remote fork -> local copy. That’s painful.

So here’s what to do:

1
2
3
4
5
6
7
8
9
git clone git://github.com/insoshi/insoshi.git
cd insoshi
git branch devel master
git checkout devel
git remote add fork git@github.com:mechfish/insoshi.git
git fetch fork
git push fork devel:refs/heads/devel
git config branch.devel.remote fork
git config branch.devel.merge refs/heads/devel

Here’s what these commands accomplish:

  • Clone the official repository and cd into the local copy.

  • Create a devel branch to develop on. Note that if we want to base our development branch on the “edge” version of the project instead of the stable version we should do this instead: $ git branch --track edge origin/edge; git branch devel edge

  • Checkout our new devel branch.

  • Add a remote named “fork” that points to our private fork on the remote server.

  • Fetch the remote fork’s contents.

  • Push our new devel branch to the remote fork, where it should have the same name.

  • Set the config for the devel branch so that it automatically pushes changes to the devel branch on the remote fork when we do a plain git push, and automatically pulls from the devel branch on the remote fork when we do a plain git pull.

Note that with this setup you automatically get the feature that a git push will push up all changes to all branches, including the master branch. (That’s because the default refspec for remotes is refs/heads/*:refs/heads/*.) So you can pull changes from origin directly to your local copy, with the assurance that those changes will be automatically migrated to your remote fork repository when you push.