Our resident Git Evangelist, Alex Scarborough, has been our workflow consultant for this project. This workflow incorporates our version control, bug tracking, and Build Server. This workflow makes concurrent development of multiple features by multiple developers easy and manageable.
Why Git?
Git is a relatively new version control solution initially designed and written by Linus Torvalds. It's absurdly fast, absurdly small, and it has a system model from which all functionality is derived. A git repository is a directed acyclic graph; a graph where nodes are connected directionally, and it's impossible to make a circle. Each commit is a node, merges are nodes with multiple parents, and a branch is caused by two (or more) nodes with the same parent. (well there's more to it than that, but lets leave it there for now).
To put it simply: git works; really-really well…and it's free. If you want more reasons, check out: http://whygitisbetterthanx.com/
Our Workflow
We are taking advantage of the easy (and functional) branching capabilities of Git to power our workflow. For each feature, or tracked-bug, we make a branch.
Each branch we create is named in the format: initials/feature_name or initials/bug-# For example: pw/bug-3 or pw/Torque3D_Beta_Merge
Here is a section of one of our graphs that represents my workflow over the course of a week:
What is this madness? Time moves from left-to-right, with the numbers (in the grey bar) representing the 8th through 16th of this month. The black line represents the master branch. Each of the other colored lines represent feature, or bug-fix branches that occurred in parallel. Each dot is a commit. When a branch is merged back in to master, it is done so in a single commit.
Why Use Feature-Branches
Using this workflow seems obtuse, at first. It is very important to discard any previous notions of branch-merging on other version control solutions. It is very easy to maintain several, simultaneous branches in development (as can be seen above), and switch between them without issues. Git commits by 'blob', not by file. This means that the same file can contribute to several branches, and several revisions in the same branch.
Using feature-branches means that you can create incremental commits during the development of your feature or bug-fix. Making atomic commits makes development much easier to manage. You can use git revert to easily undo changes, and it is very easy to go back and review how you, or someone else, developed a feature.
Merging the feature-branch back into master is done using the –no-ff flag. This tells git not to "fast-forward" the merge; guaranteeing the creation of a single "merge-commit" with two parents. This keeps all of the incremental commits in their own branch, and integrates the whole branch with master in a single commit, with the message: Merged branch 'branchname'
This makes it very easy to revert an entire bug-fix or feature with a single git revert. Performing a git revert with the SHA of a feature-branch will create a single, new commit that undoes that feature-branch; it does not remove or modify any previous commits. This allows you to go back and easily look at the development process of that feature, and hopefully easily spot, and fix, your mistake.
Keeping your development off the master branch allows multiple developers to be working on multiple features, and never have a commit conflict with their local features in-development. Performing a git pull will always resolve cleanly if you do all feature development in branches. Personally, I often have several branches active at the same time, and I may even be committing blobs from the same file, to different branches.
Integrating with Bug Tracking
After some evaluation, I picked Lighthouse for our bug tracking solution. Lighthouse is a hosted, web-based, minimalistic bug-tracking solution with a very powerful API, GitHub integration, and a Ruby interface lib. This solution has a minimum number of bug fields, and uses tags for the rest of the information. It fit my model for the build system perfectly. It is specialized, easily expandable, Ruby-based, and hosted (as a bonus).
Our workflow bug-fix branch naming convention makes it possible to easily parse out bug-fix branch merges. All bug-fix branches are named in the format initials/bug-# and these merges are done using the –no-ff flag, so a bug-fix will always go into the codebase with a single-commit, and the message will be: Merged branch 'initials/bug-#'
To facilitate the integration of our version control, and bug tracker with our workflow, we created a GitHub Post-Receive Hook server, Uttu. This server is wired in to all of our bug-tracked projects (it can manage multiple GitHub repositories and Lighthouse projects). As the README talks about in more detail, the server is managed by CI Joe. When we check in a change to the Workflow server, CI Joe will install the new version, and restart the service. I will discuss the development, and testing of this tool in a future blog.
| Ruby | | copy code | | ? |
payload['commits'].each do |commit| |
# Look for bug fixes |
if commit['message'] =~ /Merge branch '.*\/bug-(\d*)'/ |
begin |
ticket = Lighthouse::Ticket.find($1, :params => { :project_id => repoconfig['lighthouse_id'] }) |
ticket.state = 'resolved' |
ticket.body = "Fixed by #{commit['author']['name']}.\n#{commit['url']}" |
puts "Marking ticket #{$1} fixed (#{commit['message']})" if ticket.save |
rescue |
puts "Error updating ticket #{$1} (#{commit['message']})" |
end |
end |
end |
Going Further
This has only scratched the surface of our workflow, and our plans for the Workflow server. Subsequent blogs will discuss finding bugs using git bisect and other workflow processes, as well as development, testing, and additional features for the Workflow server.









