You don't have to look through too many commit histories on GitHub to see people are pretty terrible about making commits.
Now I'm not going to talk about writing commit messages. Here's the post on that. I want to talk about the equally important topic of when to make commits.
I get asked this a lot at conferences. Enough to where I made two rules I've continually put to the test.
I make a commit when:
- I complete a unit of work.
- I have changes I may want to undo.
Anytime I satisfy one of these rules, I commit that set of changes. To be clear, I commit only that set of changes. For example, if I had changes I may want to undo and changes that completed a unit of work, I'd make two commits - one containing the changes I may want to undo and one containing the changes that complete the work.
I think the second rule is pretty straightforward. So let's tackle it first. Over the course of time, you'll make some changes you know will be undone. Be it a promotional feature, patch, or other temporary change someday soon you'll want to undo that work.
If that's the case, I'll make these changes in their own commit. This way it's easy to find the changes and use git revert. This practice has proven itself time and again, I'll even commit changes I'm simply uncertain about in their own commit.
So back to the first rule.
I think generally most of us follow this rule. However, you don't have to scroll through too many repositories on GitHub to see that we're pretty bad with commits.
The discrepancies come from how we define a unit of work.
Let's start with how not to define a unit of work.
A unit of work is absolutely not based on time. Making commits every X number of minutes, hours, or days is ridiculous and would never result in a version history that provides any value outside of a chronicling system.
Yes, WIP commits are fine. But if they appear in the history of your master branch I'm coming for you!
A unit of work is not based on the type of change. Making commits for new files separate from modified files rarely makes sense. Neither does any other type abstraction: code (e.g. JavaScript vs HTML), layer (e.g. Client vs API), or location (e.g. file system).
So if a unit of work is not based on time or type, then what?
I think it's based by feature. A feature provides more context. Therein making it a far better measurement for a unit of work. Often, implicit in this context are things like time and type, as well as the nature of the change. Said another way, by basing a unit of work by feature will guide you to make commits that tell a story.
So, why not just make the first rule: I make a commit when I complete a feature?
Well, I think this a case where the journey matters. A feature can mean different things, even within the context of the same repository. A feature can also vary in size. With unit of work, you keep the flexibility to control the size of the unit. You just need to know how to measure. I've found by feature gives you the best commit.
Enjoy this post? Check out my comprehensive video series Getting Git.

Latest comments (32)
As someone who is just starting out it's tough to know "when" to commit. I've read countless resources about "how" to make a commit, but no one ever really explains when to do it. One of the comments asked about a new project, which is what I am about to embark on, your advice was to create small chunks of work to be done and commit those.
I just want to say thank you :), because that's what I am going to do with my project. It's already helping me focus on getting the right things done as well.
Excellent. I'm glad to hear this was helpful. Definitely checkout out my other articles on Git as well as the Getting Git video series.
My eternal question on the matter is to include or not the test suite as part of the unit of work. Any thoughts on this?
Absolutely include it - the tests are part of the unit of work.
Once again this discussion below has 2 types - enlightened and everyone else.
I agree with the rules, but we must emphasize master versus not master. I find most disagreement is between those who can't split the two. If you are working on master on a team you lack enlightenment, sorry brah, go back to GA and try to find an instructor who is not a burn out.
If not on master any of the reasons to commit are valid. If you commit each time your dog takes a healthy steamer on the kitchen floor, fine.
Just not on master.
When not on master (I work on local and scratch branches that never get published and squash/rebase) do as you wish. Fuck, I commit just so I can watch the diff when refactoring. I commit to make sure my cat doesn't not add some chars when I am outside the building drinking whiskey with some homeless guy. The ability to "revert to sober" is great.
What ever works for you...
Master should be squash/rebase/however you keep it clean.
I also recommend sobriety when intoxication is not appropriate.
Or is it the other way around?
I forget.
Thanks for the great article. I’m passing this around to everyone at work; we need to get more consistent with when we perform commits.
That's awesome! Glad it was helpful.
I like your approach. I started that way, then one day a hard drive got broken and I lost everything. Now I commit and push almost every 20-30 minutes on a non-production branch
You should not change your approach because of one edge case.
I know but first was the HDD, then a short circuit that started a fire (the pc burned), then the pc was stolen (second time in a series of 6 robberies) I trust more on my thumb-drive xD
Now I do as many copies that I can. I'll try the rebase comments. Just wanted to use the best process
sounds more like you should move to a nicer neighborhood lol
But really though, cloud storage is your friend. Nextcloud also exists if you would prefer to self-host - alternatively, if you're doing something with a lot of small files that get updated constantly, consider directly mounting a remote filesystem instead (lots of sync clients will trip over a high density of file changes per second)
now we have security Guards and surveillance cameras ;)
Ohh why I didn't think of that? Yes, that's a really nice solution. I'll have a backup and keep commits organized
What’s your advice on how to commit on a brand new project?
For example, when building out a server I find myself needing to do a lot of setup & I find it difficult to commit because I’m like “I’m not done yet!”
Break your work up into smaller chunks and commit those as they are ready. Maybe the project isn't done, but that piece of work is done.
There's nothing wrong with WIP commits, but based on what you described, it sounds like all your work is one big WIP commits. Which is obviously not helpful from a version control perspective.
git commit --amend:)))))))I don't trust the local storage, I need to push from time to time. So I do WIP commits.
How do you handle this?
git merge --squash?Based on experience I don't use and recommend rebase, it's too powerful and ppl brake things.
I
rebasebefore merging my feature branch. This allows me to clean up any previous commits accordingly.Just do
git rebase -iand squash them into one!Few weeks ago, I wrote a similar article about why and how creating small and useful commits: adopteungit.fr/en/methodology/2017...