Atomic commits

by Jason Swett,

Ruined soup

Let’s say I’m making a pot of tortilla soup. I’ve made tortilla soup before and it has always turned out good. This is a low-risk operation.

But for some reason, this time, I decide to get experimental (high risk). I add some cayenne pepper to the soup. Unfortunately, this makes the soup too spicy, and no one in my family except me will eat it. The soup is now basically garbage and I have to throw it out.

What just happened was bad. I mixed a small high-risk operation (cayenne) into a large low-risk operation (tortilla soup). Since cayenne is impossible to remove from soup, I’ve turned the entire operation into a high-risk operation. And, due to my poor choices, the whole operation got ruined.

Ruined bread

Now let’s say I’m making a different kind of soup, an experimental one. Let’s say I’m making another Mexican soup, pozole. I’ve never even eaten pozole before. In fact, I’m not even sure what pozole is. Who knows if my family will like it. This is a high-risk operation.

On the day I make pozole, I happen to have some homemade bread around. A lot of work went into making the bread. Unlike the pozole, the bread is a low-risk operation. In fact, it’s a no-risk operation because the bread is already made.

Since I know that bread usually goes good with soup, I decide to cut up the loaf of bread and serve it in bowls with the soup.

Unfortunately, when I serve the pozole for dinner, it’s discovered that my pozole is not good. No one, including me, eats very much. What’s more, I’ve wasted a whole loaf of homemade bread in addition to wasting the pozole ingredients.

In this case I mixed a small low-risk operation (the bread) into a large high-risk operation (the pozole). Now not only do I have to throw out the pozole but I have to throw out the bread with it.

What atomic commits are

The literal meaning of “atomic” is “cannot be cut”, from Greek. (The “a” part means “not” and the “tomic” part comes from a word that means “cut”.)

A commit that’s atomic is a commit that’s only “about” one thing. The commit can’t be cut into smaller logical pieces.

Why atomic commits are helpful

One of my programming principles is “keep everything working all the time”. It’s much easier to keep everything in a working state all the time then to allow things to slip into chaos and then try to recover.

But slipping into chaos once in a while is unavoidable. When that happens, the easiest way to get back to “order” usually isn’t to solve the problem, but rather to just blow away the bad work and revert back to your last known good state.

If your commits are non-atomic, then reverting back to your last known good state can be problematic. You’ll be forced to throw the baby out with the bathwater.

If you make my “tortilla soup mistake” and mix a small high-risk change in with a large low-risk change, then you’ll end up reverting a large amount of good work just because of a small amount of bad work. (You might be able to escape this problem if the two changes are sufficiently separate from each other but that’s often not the case.)

If you make my “pozole mistake” and mix a low-risk change in with a high-risk change, then you’ll have to revert the good change along with the bad one as well.

How to decide what constitutes an atomic commit

Unless you’re committing a one-character change, pretty much any commit could conceivably be cut into smaller pieces. So how do you decide what constitutes an atomic commit and what doesn’t?

The answer is that “atomicity” is subjective, and it’s up to you do decide. The heuristic I use to decide what to put in my commits is: the smallest thing that can be considered complete.

Sometimes when I code in front of people, they’re astonished by how frequently I make commits. But I figure since it’s super cheap to make a commit, why not turn the “commit frequency dial” up to the max?

Takeaways

  • An atomic commit is a commit that’s only “about” one thing.
  • Atomicity is subjective.
  • It’s easier to keep everything working all the time than to allow things to slip into a state of chaos and then try to recover.
  • When things do slip into a state of chaos, it’s usually cheaper to just revert to the last known working state and start over than to try to fix the actual problem.
  • Atomic commits ensure that, when you do have to revert, you don’t have to throw out the baby with the bathwater.

5 thoughts on “Atomic commits

  1. Kendall

    This is excellent. I’ve been guilty of gathering too many changes into a single commit. Your concept of “the smallest thing that can be considered complete” makes good sense and is easy to remember.

    Reply
  2. Kamal Uddin

    I was working on part time project, where my Lead developer wanted me to make every commit atomic. Initially I felt strange, but when I starting doing it, feel quit good. What is advantage is you are going to change things in such way that each commit is doing one step which must be complete.

    It was easier for review to look at code and see each commit and what it is doing, but generally I don’t think it has any value unless that specific lead. Otherwise reviewer want to see whol PR and what is going on their not atomic commit

    Reply
  3. Jóni Batista

    Do you usually work directly in the main line or do you create a separate branch (maybe with PR)?

    I am asking this because I think it affects the atomic commit strategy. For me, I like to follow atomic commits locally or in a PR branch with rebase but when I merge with mainline I might squash it because sometimes it feels like too much information in a branch where many people are working on. When I look at the mainline I want to be able to see features, user stories or bug fixes not tasks from a bug fix or user story.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *