Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
My GitHub branch-management workflow

GitHub branch management for upstream remote projects using git

My GitHub branch-management process, first attempted with OpenShot/openshot-qt but now the one I use on all projects.

  1. After creating my fork in the web interface

    $ git clone <my fork SSH identifier>; cd $PROJECT
    $ git remote add upstream <upstream HTTPS URL>
    $ git fetch upstream
    $ # $DEFAULT is the project default branch name, usually 'master' but sometimes 'develop' or whatever
    $ git branch -u upstream/$DEFAULT $DEFAULT
    Branch '$DEFAULT' set up to track remote branch '$DEFAULT' from 'upstream'.

    So now, the default branch tracks the upstream. I never touch that branch in my own fork, in fact I don't even have a local copy of it. It just allow it to fall wildly out of date, since it never updates past the point where I forked the upstream project.

  2. When I want to write code for a PR...

    $ git checkout $DEFAULT
    $ git pull # Sync with upstream/$DEFAULT
    $ # Create a new topic branch based on local $DEFAULT, which tracks upstream/$DEFAULT
    $ git checkout -b newtopic $DEFAULT
    $ git push -u origin newtopic # I do this immediately, before writing any code, to configure it
    Total 0 (delta 0), reused 0 (delta 0)
    remote: Create a pull request for 'newtopic' on GitHub by visiting:
     * [new branch]      newtopic -> newtopic
    Branch 'newtopic' set up to track remote branch 'newtopic' from 'origin'.
  3. Then after committing any changes, I can just...

    $ git push
    remote: Resolving deltas: ...
       $GITREFA..$GITREFB  newtopic -> newtopic
  4. After I finish development on newtopic...

    $ git checkout $DEFAULT # Return to upstream/$DEFAULT as my base branch
    $ git pull # Sync with upstream/$DEFAULT
  5. And if I need to return to newtopic...

    $ git checkout newtopic
    $ git merge develop # If there's already a PR, it's easier/cleaner to do this on the web and pull.

GitHub branch management for forked projects using hub

As an alternative, a different model is possible using the hub command-line client from GitHub. The basic idea behind both of these models is the same, but their execution is different enough to make them incompatible: I recommend choosing whichever feels most natural and sticking with it, rather than trying to mix-and-match (with certain exceptions, detailed at the end of this document).

  1. hub assumes you've checked out the upstream branch first (with or without hub), and don't yet have your own fork.

    $ git clone <upstream HTTPS identifier>
    $ # OR
    $ hub clone $GHUSER/$PROJECT
    Cloning into '$PROJECT'...
    $ cd $PROJECT

    Done this way, origin is already the upstream (there's no separate upstream remote), so the default branch already tracks origin/$DEFAULT. There's no need to reconfigure the local default branch.

  2. You then use hub fork to create and check out your own fork.

    $ hub fork
    Updating ferdnyc
    From git://$GHUSER/$PROJECT
     * [new branch]      $DEFAULT             -> ferdnyc/$DEFAULT
    new remote: ferdnyc

    In the hub model, your fork's remote name is your username. Other forks by other users can also be checked out, and will be named along the same pattern.

  3. Everything else is largely the same. You'd use git push -u $USERNAME newtopic to configure a topic branch to track your fork.

Using hub for pull-request management

Whether you use this repo-management model or my own, hub still has several other subcommands that can be very useful when contributing to projects. By far the most useful of them is hub pr, the command to "List or checkout GitHub pull requests".

If you want to examine the code for an UN-merged PR, for instance to compile or run the code in the state it will be after merge, simply use hub pr checkout $PR_NUM to check out the PR's branch in the submitter's fork.

$ hub pr checkout $PR_NUM
remote: Enumerating objects: 2, done.
remote: Counting objects: 100% (2/2), done.
remote: Total 3 (delta 2), reused 2 (delta 2), pack-reused 1
Unpacking objects: 100% (3/3), done.
 * [new ref]         refs/pull/$PR_NUM/head -> $SUBMITTER-$PR_BRANCH
Switched to branch '$SUBMITTER-$PR_BRANCH'

A new remote-tracking branch is created to track the submitter's fork, and that branch is then automatically checked out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment