Here at CHOAM, we love to live at the junction of creating and learning. In fact, it’s one of the primary reasons I became a programmer. As a little kid with my TI 99/4A I could create software I never dreamed possible. Sitting down with my BASIC compiler, I could type a few lines of code and suddenly do something that I could never do before. I’ve been creating ever since, the ability to create was too addictive to let go.
Software is a world where you need to improve your skills everyday.1 That’s a heavy toll, but a wonderful one, because you’re always just about underwater, you’re always challenged. But, and this is the wonderful part, you’re always discovering. Every day as a developer is a day that I am doing something that I haven’t done before. Whether it’s creating a new architecture, or just improving a workflow. Everyday is about improvement.
Problems with The Ever-Deployable Git Workflow
I’ve been using my Ever-Deployable Git Workflow for a few months now with much success. It’s been a great way to keep a project up to speed with multiple people working on multiple issues with barely any conflict. Still, nothing is perfect.
This brings up two ways that we can make the Ever-Deployable Github workflow better. First, unify with the issue tracker, and second, make better branch names.
The Github Issue Tracker
Github’s issue tracker is probably one of the least functional issue trackers I’ve ever used. It basically has nothing you’d expect or want. It’s little more than a title, some text, and maybe a label.
For that reason, it’s the best issue tracker I’ve ever used.
How many of us get sucked into the feature set of a piece of software and end up spending all of our time maintaining the software. Github’s issue tracker forces us to avoid that tendency by not giving us that feature set. It’s brilliant. All I can do is write a title, write a description, and then get back to work. It makes logging issues super fast. So recently, I’ve started to take advantage of that. I log issues for nearly every small, atomic change I want to make.
Furthermore, you can close issues with commit messages like “Fixes #216 by shuffling the JS files as if they were a deck of cards,” and the commit then gets linked to the closed issue automagically. It’s really a great system.
10 Steps to a Better Workflow
So, we have a way that we can quickly make issues to log things we want to change. And we want to get rid of insanely long branch names. Why don’t we branch the issue? This means our branch name is minimally descriptive, but there is as much description as we want in the actual issue. Using this methodology, our new Github Workflow is this:
- Only work on documented issues. The idea here is that no one is ever just blindly mucking about in the code without a documented reason2
- Look to see if anyone else is working on the issue you are going to start.
- Create an issue describing work to be done, or use an existing issue
- Create a branch using that issue number. We use “issueNUM” as the branch name, so something like “git checkout -b issue516″
- Immediately, before doing any work, push that branch back to master: “git push origin issue516.” This tells everyone that someone is actively working on this issue. This is why you don’t work on undocumented issues. It’s very easy to know what the entire team is working on.
- Work on your code following The Ever-Deployable Github Workflow. Making commits fairly atomically, or as atomically as your team decides.3
- Rebase to master
- Commit the branch with a final message like “Fixes #517 by doing lots of stuff.”
- Push to remote, submit your pull request, and “git checkout -b <nextIssueNumber>”
- Lather, rinse, and repeat
Fixing other things along the way
This workflow has done a few things for us. One, it encourages atomic work on the code. By that, I mean it encourages us to stay away from commits that change “a little of this, little of that.” We are working on a single issue, and our branch is named with that issue. So we focus on that issue.
If we want to fix other, most often very small, issues during the work, we fix them in a single commit, and log that in the commit message “Fixes #214 by changing something, since I’m here already.” If we want to fix bigger issues, we do it a bit differently.
For instance, say we are working on our issue #516, and during that, we come up with a decent way to correct another issue, say issue #212, that comes up because of our work on this one, but which we don’t want to dump right into production- maybe we have to test it more:
git checkout -b issue516 git push origin issue516 … do some work and decide to fix issue 212, but not to push it to production without first finishing 516 git checkout -b issue212 git push origin issue212 … fix 212 and commit git commit -am "Fixes #212 by mucking about in the code" git push origin issue212 git checkout issue516 … continue working on issue 516 git commit -am "Fixes #516" … then do the standard git rebase workflow: git checkout master git pull origin master git checkout issue516 git rebase master … Then submit your pull request for Issue 516. Now, it's a good time to push up 212 git checkout issue212 git rebase issue516 git push origin issue212
With this, issue212 is fixed on top of issue516 and is ready for either a pull request or more review and work. From a git log perspective, it appears that issue 516 was completed, and then issue 212 was completed. Nice and clean.
I’ve been using this workflow on various teams for about 2 months now, and it’s working out extremely well. I’d be interested in what you think.
- Admittedly, there are those who don’t. But I try to keep them far away from my projects. Nothing is more dangerous than a developer who is happy at being stale [↩]
- or at least without creating an issue like “Issue #516: Blindly mucking about in the code” [↩]
- I like smaller commits, since they are easier to review and revert [↩]