github forking2011-09-09 16:25:23 -0700 git tech
I don't think GitHub's default workflow for forking a repo is ideal for my needs. Most of the time when I fork a repo, my aim is to fix something or add a small new feature which I will eventually submit upstream as a pull request. While I am hacking away or living with my modifications for a while before I submit them, I want to continue to be able to easily pull in upstream changes as well. So whenever I fork a repo, I want the following:
masterbranch will track the pristine upstream master. Whenever I have no changes of my own pending, I can just switch my work tree to use
masterto keep up with the latest changes with a simple
- A volatile
hackbranch where I work on my changes. This is volatile since I'll regularly be rebasing onto the head of
- A volatile
pullmebranch where I will put changes that are ready for a pull request submission. I may want to continue to hack away in
hackwhile I'm waiting for the resolution of my pull request, so this is analogous to a release branch. But this is volatile since, for the sake of simplicity, I'll be resetting it whenever I'm ready to submit a new pull request.
(By volatile, I mean that I can feel free to rewrite the history on these branches without repercussions.)
So here's how I go about forking a GitHub repo:
git clone <upstream_repo> # e.g. http://github.com/mxcl/homebrew.git cd <upstream_repo_name> # e.g. homebrew git remote add fork <forked_repo> # e.g. firstname.lastname@example.org:SethMilliken/homebrew.git git config branch.hack.remote fork git config branch.hack.merge refs/heads/hack git branch --no-track hack origin/master git push fork hack:refs/heads/hack git checkout hack
At this point here's how things look branches-wise:
$ git branch -r * hack master remotes/fork/hack remotes/fork/master remotes/origin/HEAD -> origin/master remotes/origin/master
remotes/fork/master is what the GitHub website uses for it's default branch. I like to clean this up to remove any chance of ambiguity about the name
master. To me,
master always means the authoritative branch from the canonical repository, never a branch in my fork. Here is how I tidy this up:
- Click the
Adminbutton on the forked repo's GitHub page.
- Change the
Default Branchto "hack".
- Delete the forked repo's
git push fork :master.
If there were a way to name the default branch when you first fork, or to subsequently rename it via a commandline git command, that would simplify things a bit.
To rebase my changes onto incoming upstream, which I do periodically as I'm hacking, and again immediately before submitting a pull request:
git pull --rebase origin master
When I'm finally ready to submit a pull request, here is what I do:
git branch -f pullme hack git push fork pullme:refs/heads/pullme
This essentially replaces the
pullme branch with the current state of the
And after my pull request is accepted, I switch back to
git checkout master