When I get asked about tools for quality assurance, I will pretty much always mention that the technology is not the answer. In my experience, the best improvements in quality come from process, from letting as many people as possible have access to all aspects of the system as early and often as possible (this is exactly why evolving projects "release early, release often"). A great tactic is to have another developer review each change - but what do you do if, like me, you work alone? Continue reading
As a lead on an open source project, I spend a lot of time merging awesome contributions from our community into our main repo on github. Sadly, some of them are slightly less awesome (rarely but it does happen) and I sometimes need to unpick what happened to understand the problem and give good feedback. Since the project is hosted on Github, this means having some git tricks up my sleeve, and I thought I'd share.
I have the main repo cloned onto my local machine. Before I do anything, I fetch and merge from the origin and then push back to it, so I know my repo is in sync with the github one. Then I fetch the branch I want to merge - usually one that we've got a pull request for. To see what's in the branch:
git log [branch] --not master
This is nice because it doesn't show what's in the master branch of this repo but missing from the incoming branch, it just shows me what's new on this branch.
I can diff and merge at this point, but more than once I've merged and then wondered what changes I have in my repo that aren't in the github one (this is where it is helpful to have fetched from the remote one first). I have the github repo mapped as "origin" as per the excellent documentation so I can just do:
git diff origin/master..HEAD
This shows me the differences that are in my current repo as compared to origin/master, which is the tip of the main repo shown at the version it was when I last fetched it. I particularly use this when I've merged someone's changes in for testing and am wondering quite what was supposed to happen - sometimes just reading the diff beforehand isn't enough, it's only when I get the code merged I realise something unexpected is happening!
In October I will be speaking at the PHP London user group on Thursday 7th at the Theodore Bullfrog pub in London. I'm giving a new talk called "The Source Control Landscape", looking at the products currently available in the source control arena, how the distributed systems have changed the landscape, and how we can choose between them all today. I'm really looking forward to the event, it's always a good crowd and I love to meet new people as well as meet up with existing friends - see you there :)
Recently, a github project that I contribute to, joind.in, moved from an ordinary github user account over to an organization. Getting contributors moved over is pretty straight forward, I have a fork of the main repo on github at http://github.com/lornajane/joind.in and that updated to show itself as being a fork of the organisation's repo rather than the original user repo that it had been set up under.
In fact, all I had to do was update my upstream remote on my local repo - I set this up following the excellent github forking instructions when I first forked the repo. All I did then was to check my remotes:
This showed my remotes with the "upstream" pointing to the old repo. So I copied the URL of the organization repo, removed the old version and added a new upstream:
git remote rm upstream git remote add upstream git://github.com/joindin/joind.in.git
Everything now behaves as before while handling the new central repo for the project - hopefully this helps others with projects moving from user accounts to organizations (or organisations, as I keep typing, British spellings as always!)
Recently I've been doing more git than I ever intended to, working with the Joind.in codebase, contributing and managing contributions to that. I quickly realised that I needed to make changes on branches, and since I'm new to git, it took a while to figure some of this out. I'm pretty confident now* so I thought I'd share how I work with branches in git.
Available Branches and The Current Branch
This is the easy bit:
$ git branch * api master $
The entry with the star next to it is the current branch, so here you can see that I have branches "master" and "api" and I'm currently working on the "api" branch. If you only have one branch it will usually be called "master".
Creating and Changing Branches
My experience is with Subversion until now, and branching is really different in git (because it actually has branches rather than just copies, this is definitely a feature, but it is a different approach from how I had used them before). So you can switch your working copy around to look at different branches, which threw me a bit to begin with. To change branches, just checkout the one you want:
$ git checkout master Switched to branch 'master' $
If you actually wanted a new branch simply name it and ask checkout to create it if it doesn't exist, by using the -b switch:
$ git checkout -b demo Switched to a new branch 'demo' $
So now my branch command shows me this:
$ git branch api * demo master $
This is very much an optional step. Many of my branches are private branches - meaning that I branch on the development server, finish the feature at hand, and then merge the changes into my master branch without pushing the branch to anywhere else. To share changes with others though, I sometimes like to push my changes up to github - which is my "origin" remote on my repo. So to push the demo branch we just made, I would simply do:
$git push origin demo Total 0 (delta 0), reused 0 (delta 0) To firstname.lastname@example.org:lornajane/joind.in.git * [new branch] demo -> demo $
If you use "git push" on its own, it will push all branches which exist on both the local repo and the origin - but will not push any private branches unless you specify that it should.
The http://help.github.com site, Github's own documentation, is actually brilliant and has really helped me to get up to speed with working with my own code and contributions from others.
* The only problem I've had with code on github recently is that I merged totally the wrong changeset into the main project root. Which really isn't the fault of the source control system :)
Next week I will be making the trip to my original home town of Birmingham to speak at the PHP West Midlands User Group, on 6th April. They are an active user group and although I haven't managed to organise myself to attend their meetings before, I do keep meeting their members at other technical events so I know they are a good crowd and I'm looking forward to this! My talk will be "SVN in a Distributed World" - looking at the features of SVN, of the distributed source control solutions, and thinking about whether SVN is now an outdated technology or whether it is still a good choice for source control.
Hope to see you there!
Recently I've been contributing to the code project behind joind.in, the event information and feedback site. I rely on joind.in a lot and after putting up with a frankly astonishing volume of feature requests from me, its owner Chris Cornutt very politely suggested that I might like to fix some of them myself. The project is hosted on github and I haven't traditionally been much of a git fan, but I wanted to contribute so I set off to work out how to begin.
Register on Github
To do anything useful I first needed to sign up for an account. Github has a range of accounts but I found that with one of their free accounts I would be able to get started and contribute to the project. This gives me a project space of my own and a user to tie all my activities to.
Set up SSH Key
In order to authenticate against the github servers, you need to set up an ssh key and give them your public key so they know you are you. You'll then need to tell git to use this key whenever it makes contact with the github servers. I do quite a bit with ssh and ssh keys myself so I was comfortable with this step. Even if you are totally new, its still pretty straightforward and they have a great howto on github itself which will help.
I had issues with git not picking up that it needed to use a non-standard ssh key, but I found the answers in this entry on the git website. In a nutshell, set up an ssh alias, set the key in there and then use the alias instead of the actual URL when giving the repo location to git. This now works like a charm for me.
Fork the Project
Now, github uses "fork" where I might choose to say "checkout" - fork in my world means something else completely. But in this case you're just making your own copy of the project repository. This is where you will commit your changes to and it retains its link with the original repository making it easy for anyone with commit access to that to pull in your changes. Patch files are nowhere to be seen, and although I was wary at first, this is project collaboration at its most painless, I'm impressed! Forking was relatively simple and again there was great documentation on the github site. In particular I recommend that you take the time to follow the bit about adding an alias for the "upstream" repository - this made committing my changes to the main joind.in repo really easy.
The forking instructions linked above also gave a description of how to actually use git, how to get my changes applied to my local repo, and how to push them to my remote repo on github itself.
Make a Pull Request
Once I'd fixed a few things, I was ready to push the code back to the main project so that Chris could consider it for inclusion. This is done by making a pull request from the main project page - you can add a comment about the changes you are supplying to help the maintainers to manage all the incoming patches.
Go Forth and Contribute
It was easier than I expected to get set up to contribute to a project using github, so find something you want to improve and/or be involved with, and do it. I began by fixing the docs for joind.in, which was a great place to start since it allowed me to make a useful contribution without touching the code in the first instance :)