Let’s say you’re going to work on an open source project on GitHub. That’s a nice thing to do. Definitely do that. You’ll probably want to:
- Get a copy of the code
- Make changes
- Raise PRs so that the owners of the code can review and approve
All of this is supported with GitHub. Other git providers also exist. Given that GitHub is the main place you’re likely to do this, let’s walk through the process of creating a fork, keeping it up to date, and making changes for review.
If you’ve already done this and broken your fork, then read my guide on unbreaking a fork. I’m going to provide you an opinionated way to operate your fork, to make things easy. Other approaches might also work, but these seem to be low friction.
To ensure that you keep your clone in good order, I recommend reading my guide on feature branches, squashing and rebasing.
- Create a fork using GitHub’s fork button (top right of a repo)
- Clone it to your working folder
- Add an upstream to your cloned copy
- Make changes on a feature branching taken from your master (or other copy of an appropriate upstream branch)
- For submitting changes, create PRs from your feature branch to the appropriate branch on the upstream.
- Periodically rebase your master (or other main branch) against its equivalent in the upstream.
- Propagate those changes to feature branches.
Adding an Upstream
Go to the original repository in GitHub and drop down the Clone button to find the url of their repository. Use this to add an upstream to your clone:
# in my clone of my fork from AssertJ git remote add upstream email@example.com:joel-costigliola/assertj-core.git # now I can keep track of the upstream with: git fetch upstream
Creating a Feature Branch
When you do GitHub flow, you start on a main branch – usually master and you create a branch from the head of it in order to make change:
# if you're not already on master git checkout master # if you don't have your own latest HEAD git pull # now create a new branch git checkout -b some_new_branch
On this feature branch you can develop to your hearts content. My advice is that, at the end of development you squash that branch, ready for any rebasing. See the article here on that.
Update From Upstream
If during your development the upstream has moved, you’ll want to either bring in their changes, or make your commit a cleaner merge into their repo. This requires you to bring your master up to date with the upstream. That’s your master both locally and up on the git server.
# get up to date commits git fetch upstream # go to your master git checkout master # bring it up to date with its # upstream counterpart git rebase upstream/master # and then push up to your fork git push
Update a Feature Branch Afterwards
Having brought your master up to date, you’ll want to rebase your feature branch.
# go to your feature branch git checkout my_feature_branch # if you've already rebased your master # then you just need to rebase your feature branch git rebase master
What if it goes wrong?
You can’t avoid things like merge conflicts – they’re part of the process of bringing conflicting code together.
You can always abort rebases with git rebase –abort if something’s going wrong.
Similarly, if you’ve screwed up your local branch, then try git reflog to see all the commits you’ve had recently and what you’ve been doing to them. If necessary you can force the current branch to point to one of those happier commits with git reset <commitid> –hard but be wary of doing this with master.
If you’ve rewritten your git tree and want to push to the remote, you may get a complaint if your changes are not fast forwards. Don’t just pull and merge! If you’re sure your local branch is in the right condition, you can push it up to the server with git push -f to force it to overwrite what’s there.
Please note: this is not a git tech support site… so modify your repos at your own risk.