For Contributors: Managing a fork and keeping it up to date

Let’s say you have forked a repository on GitHub and you’ve started working on a feature or a bug fix that you plan on contributing as a pull request at some point. One issue you’ll run into eventually is how to keep your fork up to date with the upstream repository. Here are some instructions I’ve followed to manage a fork and keep it up to date.

First of all, create a new branch on which to make all of your commits. Theoretically, if you only ever plan on contributing one pull request, you can get away with adding the commits to the main branch (e.g., master). However, it makes it harder to contribute multiple pull requests and it makes it harder to keep that main branch up to date.

Create and switch to a new branch. For the following examples I’ll assume I’ve forked the django repo.

git clone https://github.com/machristie/django.git
cd django
git checkout -b my-branch

After you make some commits and are ready to push them to your fork, do the following:

git push -u origin my-branch

The -u option to git push means to set this branch (my-branch) to track this remote branch (origin/my-branch) as its upstream branch. What this means is that from here on you can simply run git push or git pull and git will push/pull to this remote branch (origin/my-branch). Just to clarify here origin is your fork.

Second, now that you are doing all of your work off the main branches, set the main branches to track the remote branches in the upstream repo. Then you can easily do a git pull to bring your local main branch up to date.

Let’s add the upstream repo as a Git remote.

git remote add upstream https://github.com/django/django.git
git fetch upstream

Now let’s set the master branch to track the remote branch in this upstream repo.

git checkout master
git branch --set-upstream-to=upstream/master

Now we can do a git pull

git pull

The main branch(es) now are set up to sync with the upstream repo while the branches you create are set up to sync with your fork.

By the way, if you want to update a main branch in your forked repository you can do that too. For example, to update the master branch in your fork to bring it up to date with the master branch in the upstream repository you would switch to your master branch, update it with upstream, then push those updates to your fork:

git checkout master
git pull
git push origin master

At some point you’ll want to update your branch so it has the most recent commits from the main branch. For example, let’s say you create my-branch off of the master branch and now you want to update your my-branch with the latest commits on master that have landed in the upstream repository in the meantime. To do this you can first pull in updates for master from the upstream repo and then rebase your branch with master. Here’s how:

git checkout master
git pull
git checkout my-branch
git rebase master

git rebase master rewrites your commits on your branch on top of the latest commits on master.

Of course, when you do this you might run into merge conflicts. When you run git rebase master it will try to re-apply all of your commits, one by one, on top of the last commit on master. If there are changes on master and also on your branch to the same lines of code in a file, git won’t be able to figure out how to automatically merge those changes. The rebase will stop and tell you that there are merge conflicts. Running git status will contain a section called Unmerged paths, something like the following:

Unmerged paths:
  (use "git add <file>..." to mark resolution)

    both modified:      somefile.txt

For each one of the files listed in Unmerged paths:
1. Open the file in a text editor and inspect the conflicting changes. The conflicts are delimited by <<<<<<<, ======= and >>>>>>> markers.
2. Decide which side to keep or manually merge the changes, as needed. Save the file.
3. Run git add path/to/file

Once you’ve resolved all of the merge conflicts, run:

git rebase --continue

Git will continue with the rebase as best it can. It may stop the rebase process multiple times if there are more merge conflicts.

For more information on resolving merge conflicts, see the section on Basic Merging in the Pro Git book.

Leave a comment

Leave a Reply

%d bloggers like this: