On Friday, I finally became active on GitHub, something I’ve waited far too long to do. My first action was to fork Jeremie Miller’s Locker project. In the process of doing that, I captured some notes about working on projects at GitHub, which I’m posting here in case others might find them useful. I know I’ll be referring to this post until these commands become second nature.
First things first, you’ll need to have a GitHub account, associated with your SSH public key for authentication. I had done that previously, according to GitHub’s helpful instructions. In fact, GitHub has done a terrific job of documentation, and I highly recommend reading through Help.GitHub if your are new to either Git or GitHub.
With that out of the way, we can get on with the business of forking a project. Each project on GitHub has a Fork button. Clicking it will create a forked repository in your account.
Now that we have a forked repository, we can begin developing.
First, clone the repository to your development system.
$ git clone email@example.com:jaredhanson/Locker.git
$ cd Locker
Let’s examine the clone a bit.
$ git branch -a
remotes/origin/HEAD -> origin/master
$ git remote -v
origin firstname.lastname@example.org:jaredhanson/Locker.git (fetch)
origin email@example.com:jaredhanson/Locker.git (push)
You can see from this that we have a local master branch, and a remote master branch. The remote branch is aliased to origin, and its location is your account’s repository.
We are going to want to track changes from the original project, so lets add it as a remote repository, aliased to upstream, and fetch it.
$ git remote add upstream git://github.com/quartzjer/Locker.git
$ git fetch upstream
At the time I first forked the project, there were bugs, some of which were fixed by Philip Harrison in his fork. So, we are going to add that fork as a remote repository, fetch it, and merge the changes in.
$ git remote add harrison-github git://github.com/Harrison/Locker.git
$ git fetch harrison-github
Before merging the changes, however, we are going to make a local branch in which to do our work. This branch allows us to isolate our modifications, eliminating any worry about making the master branch unstable. This is typical in Git workflows, because branches are cheap to create and easy to merge. We will call our branch session-secret, which is descriptive of the work we will be doing on it.
$ git branch session-secret
$ git checkout session-secret
Now that we have switched to a new branch, we will merge in the changes.
$ git merge harrison-github/connect_secret
Merge made by recursive.
Ops/Dashboard/dashboard.js | 2 +-
locker.js | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
We can see that changes to two files were merged into the branch. However, there are some more session secret-related bugs that I know about, so I’m going to go ahead and fix those myself. Once I’ve completed that work, I can check the status of the repository to see what has been modified.
$ git status
# On branch session-secret
# Changed but not updated:
# (use "git add ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
# modified: Apps/HelloWorld/hello.js
# modified: Apps/MergedContacts/contacts.js
# modified: Connectors/AmazonHistory/server.js
# modified: Connectors/ChromeHistory/client.js
# modified: Connectors/Facebook/client.js
# modified: Connectors/Flickr/client.js
# modified: Connectors/IMAP/demo.js
# modified: Connectors/Twitter/client.js
# modified: Connectors/Twitter/pull_contacts.js
# modified: Connectors/foursquare/client.js
# modified: Contexts/facebook.js
no changes added to commit (use "git add" and/or "git commit -a")
I’ve modified some files with bug fixes, which I’ll add and commit.
$ git add -u
$ git commit -m “Add session secret, which is now required by Connect."
With all the fixes applied to the branch, we can now push the branch to GitHub. Once the branch is available there, GitHub provides tools to submit pull requests, allowing the maintainer to bring changes from our fork into the upstream repository.
$ git push origin session-secret
Our work on that branch is complete. We’ve tested it and are satisfied that the changes are stable, so let’s merge them into the master branch.
$ git checkout master
$ git merge session-secret
Now let’s do a quick review of the changes between our development system and our GitHub repository.
$ git diff origin/master
The changes look OK, so let’s push the master branch up to the origin repository.
$ git push origin master
With everything up-to-date, our work is a wrap.
Since Friday, development on the upstream repository has continued. My changes have been pulled in, and changes from other developers have been committed.
Let’s fetch the upstream repository and review the changes.
$ git fetch upstream
$ git diff upstream/master
The changes pass our review, so we will merge them straight into our master branch.
$ git merge upstream/master
Now, let’s examine the status of our local clone. Since we just pulled in changes from the upstream repository, our forked repository on GitHub is now out-of-date.
$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
nothing to commit (working directory clean)
It’s our goal to track changes as closely as possible, keeping all repositories up-to-date, so let’s go ahead and push the new changes into our repository.
$ git push origin master
Since we are tidying up, we will also delete our session-secret branch from both the local and remote repository. The changes it contained have been merged into the upstream repository, so the branch is no longer needed.
$ git branch -d session-secret
$ git push origin :session-secret