Michael Ivey recently wrote about his git work flow over at My Git Workflow and it turned out to be a pretty useful article and was just the encouragement that i needed to blog about my own experience. Although I’ve used git before, I much rather use bzr whenever possible. I’m not into religious wars about tools, so use whatever you like.
I work as an independent programmer(freelance programmer if you prefer) and so I am often working on several projects at the same time, mostly on my own, but sometimes with 1 or 2 more people involved.
I use standalone branches in bzr so they will have their own directories. I create a parent folder with the name of the project, say KillerIdeaX. And inside it, i would have the project’s branches. One called KillerIdeaXtrunk which is the stable version of the project. And other branches called feature branches for…well, features.
bzr init KillerIdeaXtrunk
bzr branch KillerIdeaXtrunk KillerIdeaXFeatureA
bzr merge KillerIdeaXFeatureA KillerIdeaXtrunk
If the project is small enough, i would just have the trunk folder and i work on that. But usually, the project will have a number of distinct features. So i create feature branches and work on those and merge them back into trunk after testing. The trunk branch is also where i take snapshots from to deliver to the client. So i always know that what i am delivering is a stable build.
If i am working with other people, i use an approach that is similar to feature branches. Whenever i receive code from the client(or co-worker), i create a standalone branch such as KillerIdeaXWithFooFeature and thus be able to quickly see what is different using bzr commands(such as diff and others).
Say Cheese! Tag!
I mentioned taking snapshots from the trunk to deliver to the client for testing but i didn’t explain how. What i usually do is simply export the code from trunk(which would always give me a stable build) and then tag that version so that i know which version the client is talking about when i get the inevitable email telling me that the whole thing is broken.
...receive angry email from client demanding a prototype...
bzr export KillerIdeaXtrunk KillerIdeaX.zip
....email KillerIdeaX.zip to client with usual warnings about software prototypes...
bzr tag "0.1"
....now we can both argue about same codebase....
I need more shelf space
When you begin using any version control system, it might be somewhat challenging to learn to code via separate changes as entities. So one feature would be one change, one bug fix would be another change and so on. Changes are grouped logically. As in, what are the modifications that logically fit together. That way, it becomes much easier to roll back certain changes or to chase down bugs or retrieve an earlier version of the codebase…etc.
While this is a proper programming practice, it sometimes can be hard to follow. So let’s say you’re working on some feature and while testing it, discover an unrelated bug. The proper thing to do would be to branch out from your last revision, work on that branch to fix the bug and then merge the changes back in and then go on working on your feature. This makes sense, though, only if the bug fix is significant enough. Often, fixes are one liner changes and so it will be much faster to simply fix in place. Of course, doing that would ruin your ability to separate changes and so rolling back your feature for what ever reason also means losing that bug fix.
This scenario is excellent for the shelve command in the bzrtools plugin(recent versions of bzr have this command built-in in a slightly modified way). The shelve command interactively asks you about the changes in the source code(by hunk) and asks you if you want to keep it or shelve it. Shelving changes simply removes them and stores them in a temporary location until they’re un-shelved.
....working in KillerIdeaXFeatureA branch, discover unrelated bug....
....choose to shelve all changes related to feature...
....introduce one liner fix for bug...
bzr commit -m "fixed silly bug related to foobar problem"
...continue working on feature....
bzr commit -m "implemented awesome feature zazzle"
Note that using the shelve command, you can shelve and un-shelve any change you want. So you could’ve introduced the one line fix and then before committing the feature shelved that instead for example.
Can you see it?
As you can see, there’s a lot that you can do to optimize your process and using a distributed version control system means that the administration overhead of a centralized one is no longer there. So you really have no excuse not to make use of its power…even if you’re a solo programmer.
(I tried to stay away from bzr terminology in this article to give you a general idea of the tool. But do check out the great documentation that comes with it.)