A very simplified overview of a common workflow without any assumption of a formal version control system is:
- design the entire project up-front
- parcel out discrete parts of the project to teams
- parcel out duties in those teams to developers
- assemble developers’ work within the teams and coordinate integration
- assemble teams’ work within the larger project and coordinate integration
Individual developer workflow in those circumstances tends to center around ad-hoc local management of backup copies and a lot of trial and error. All too often, “undoing” an erroneous change results in rewriting the affected code from scratch.
Given a centralized version control system, code is often checked into a central repository only as features are added to the discrete chunks, so that (hopefully) everything works when code is checked in and nobody else is subjected to broken code in the repository. For the individual developer, though, not much changes in his or her local workflow, aside from the fact that screwing up badly enough on the local codebase can be fixed by checking out the last “backup” in the central repository.
Distributed version control systems (DVCS) like Mercurial drastically change the workflow options for a development project, at every level, however. For instance, at the local level an individual developer can actually collaborate with other developers whose responsibilities do not directly overlap more easily, in an ad-hoc manner. Perhaps more importantly, the individual developer very easily maintains a local repository where all changes can be checked in along the way to working code, locally. Broken code is not a problem in this case, because nobody else needs to see it most of the time, allowing the individual developer to gain all the benefits of version control at all times.
It is relatively easy to do the same at the team level, as well. This way, each team can be its own sub-project, with its own copy of the complete repository, with individual developers’ code being checked in on an as-needed basis for access by other members of the team. When only one other member of the team needs a particular version of some other member’s code, however, even the team’s repository can be bypassed.
Similarly, teams can share code between them without necessarily having to commit to the entire project’s repository, such as when coordinating development for features that exist as supersets of different teams’ domains of responsibility. Ultimately, then, teams can check in code to the central project when that code is sufficiently complete and mature to share with the rest of the teams on the project as part of the official codebase.
When working on this project, a process that ensures only working code gets shared with the world at large should be employed. Your workflow should also tend to spare you from difficult management of multiheaded hydras for your project repository, so that the likelihood of having to deal with messy merges is minimized. Toward this end, the following workflow is recommended, using Mercurial:
- pull latest version of the project
- write code
- I do not presume to tell you how to go about writing good code.
- You should probably have some embedded development workflow here.
- commit code (often)
- This may happen many times as part of step 2.
- This is only a local commit. Remember, you’re using a DVCS.
- push changes
- Pull to ensure you have a current version of the project.
- Others may have pushed changes while you were working.
- If you pulled changes, you may have to merge.
- If there were no changes pulled, the merge step is unnecessary.
- If there was no merge performed, the commit is unnecessary.
- Pushing changes sends them to the “central” project repository.
This example workflow document is adapted from a document I wrote for a small open source software development project hosted on BitBucket, a Mercurial-based code hosting site, and is distributed under the terms of the Open Works License, so you are free to modify and redistribute it within the terms of that license.
Remember that distributed version control offers possibilities for your development project workflow that do not exist with centralized version control systems. You should especially remember that the benefits of version control are much greater when you do not have to refrain from committing code until you are sure it will not break the working codebase. One of the most important benefits of using a DVCS is the way it enables you to commit often — every time you save a modified file, every time you get up from your keyboard to refill your coffee, any time you do anything that represents a discrete change or stopping point, no matter how small.
Increasing the frequency with which you commit to your local repository ensures you are better protected against disaster and error, and gives you a clear record of the development path. It provides an easy way to create branches from earlier points in local development so you can try a different approach and compare with the approach you have been following when you find you are running into a dead end. It also allows you to break out changes as patches to apply to an alternate development branch as needed, or to show another developer the path of your progress when discussing the approach to your work on a particular feature.
Using a DVCS does not force you to adopt a new way of thinking about your workflow, but it does allow a new way of thinking about it, and that is a good thing. Take advantage of it.
Related reading: Secure Mercurial and BitBucket for your development projects.