Developer Tip: Keep Your Commits “Atomic”
Source control is a developer’s best friend. The ability to share code with multiple developers, track changes, and easily roll back when problems arise is indispensable in this distributed world.
One question that often arises when first getting started with source control (it doesn’t matter if it’s Git, SVN, TFS, or others) is “What do I check in, and how often do I do it?” My answer is to make your changes as small and “atomic” as possible. I’ll explain more below.
An “atomic” change revolves around one task or one fix.
Recently I received an e-mail with a list of layout changes and a bug fix to make on a web application I was working on. All of these changes were very simple. One approach to this would have been to simply make all the changes/fixes, commit them to the repository, and be done with it. However, what happens if the bug fix introduced another error or didn’t actually fix the problem?
General best practice says that you would roll back your recent commit, make the proper fix, and recommit things again. However, if you did that, you would lose all of the layout changes (which work just fine) and you would be doing additional work to re-apply the layout changes. In addition, creating another commit to “fix the bug fix” isn’t a good approach either.
Instead, commit the bug fix as one change, and the layout changes as a separate one. That way you can easily roll back the bug fix without affecting the layout change. I would even say to commit each layout change separately as well, because it makes it easier to change the layout on the fly, or roll back a simple color change without affecting the other updates involved.
When working with new features, an atomic commit will often consist of multiple files, since a layout file, code behind file, and additional resources may have been added/modified. You don’t want to commit all of these separately, because if you had to roll back the application to a state before the feature was added, it would involve multiple commit entries, and that can get confusing. This also helps out when merging features to other branches, because you can easily select that single commit entry to merge, and all the appropriate files will be merged over. I’ve used this on several occasions with much success.
The common thought with those new to source control is to commit “at the end of the work day”, or “whenever I feel like it”, or whenever a batch of fixes are complete. Avoid those pitfalls and consider what an “atomic” block of work is and make a commit only when that is complete. It may make your commit history more verbose, but in the end it will make your overall project a lot more flexible for bug fixes, feature migrations, and rollbacks.
- Commit each fix or task as a separate change
- Only commit when a block of work is complete
- Commit each layout change separately
- Joint commit for layout file, code behind file, and additional resources
- Easy to roll back without affecting other changes
- Easy to make other changes on the fly
- Easy to merge features to other branches
If you’d like to read up further on the issue, and see some great examples, check out this article by Benjamin Sandofsky focusing on Git. If you’re in the SVN camp, Apache has some good best practice guidelines and there is always the “bean book“.