So you want to contribute to a Git project on GitHub or CodePlex. The first thing you always do here is create a fork, which is easy enough:
After you create your fork, you’ll likely then clone that forked repository locally like:
git clone email@example.com:jbogard/AutoMapper.git
That’ll create a remote called “origin” that points up to your fork (in this case, on github). Check out the Git book for more info on remotes.
But we’re not quite done. We’ve created a fork, which is its own entire repository, separate from the original “central” repository:
In this new distributed reality, we need to be able to work with those upstream repositories effectively.
If you want to make changes locally, great! But always make those changes in a branch. What we want to do is still be able to pull in any upstream changes, but isolate any contributions we make to the project. In order to do so, we’ll always create a local AND remote branch for any work we do. Our workflow looks like this:
git checkout -b MyFeature **work work work & commit changes locally** git push origin MyFeature
The reason we want to isolate our custom work from the master branch is that it makes it much, much easier to integrate and keep up to date with upstream changes. An example in GitHub is:
I have two branches – the default “master” branch, and one that I’m going to isolate for a pull request. The nice thing about CodePlex and GitHub is that they both allow you to “add” changes in the form of commits to your pull request. By isolating potential pull requests into a separate, dedicated remote branch, we can ensure that we don’t paint ourselves into a corner where we want to pull in upstream changes or work on something else.
Branches – local and remote – isolate work, and both GitHub and CodePlex work well with branches as pull requests.
When you’re done with any upstream changes, and our pull request is either accepted or rejected – kill your local and remote branch:
git branch -D MyFeature git push origin :MyFeature
Once our changes are integrated (if they are), we want to use the upstream repository’s version of our changes.
Pulling upstream changes
When you create a fork, you’ll also want a way to keep up to date with the upstream repository. The first thing to do will be to add a remote that points to the upstream repository (conventionally named “upstream”):
git remote add upstream git://github.com/AutoMapper/AutoMapper.git
With that remote added, we want to fetch upstream, merge all local branches with that repository, and push that to our upstream:
git checkout master git fetch upstream git merge upstream/master (for each upstream branch) git push origin
- Fetches all upstream commits
- Merges our local branches (as fast-forward merges) to the upstream’s repository’s versions
- Synchronizes our fork with upstream changes by pushing our local repository up.
It’s a little weird that we have to work with our local repository to synchronize our fork with the upstream repository, but that’s just because it would be a little hard to try and do that directly in GitHub.
The *first* thing you should do after forking a project and cloning that fork locally is add that “upstream” remote. It’s just much, much easier to have it set up early and get into the flow of fetch, merge, push for incorporating upstream changes.
To review, working with forks on GitHub and CodePlex is easy if we do two things:
- Create an “upstream” remote to represent the repository our fork originated from
- Always work in named local and remote branches for any commits we do in our fork
For more info, check out GitHub’s help pages.