Two Life-Changing Git Habits

Last month, I decided to read Pro Git cover-to-cover. I’d previously stumbled across the book as a helpful reference for getting unstuck in gnarly branch entanglements and rebases gone awry.

But I never felt totally comfortable in those situations, and decided it was time to gain a better understanding of a tool I use all day every day.

I’d highly recommend giving it a read, if only to develop a better mental map of the Git command landscape. Knowing what’s possible can help so much when you encounter new problems to solve.

That said, this particular post isn’t strictly about Pro Git. It’s about two habits I’ve picked up since reading it that have fundamentally changed how I use Git day-to-day (so “life-changing” is not a complete exaggeration).

Habit #1: Always use interactive staging

My normal workflow before I started using interactive staging went something like this:

  1. Make changes and write code until something is mostly feature-complete (or until a “good stopping point”)
  2. Run git status as a gut check to remember what I’d changed
  3. Stage the modified files and commit
  4. Repeat

The problem with this workflow is that I rarely scoped changes to separate commits—mostly because I didn’t want to leave “the zone”.

These days, I default to staging patches, with the magical command: git add --patch.

The --patch flag (an abbreviated -p also works) lets you interactively flip through each change you’ve made and decide whether to stage it—even if changes are part of the same file.

I’ve found this workflow feels much more natural to me than switching contexts after every minor change. Rather than break flow to make a commit (then wait for tests and any other pre-commit hooks to run), I just work until something is functionally complete. Only then do I break changes into meaningful commits.

Another benefit is that interactive staging acts as an editing and review phase. Viewing all your changes one by one in a new context makes it a natural spot to catch mistakes and opportunities for improvement.

This post isn’t a guide to using interactive staging, but you can get a primer, or check out this excellent screencast from John Kary’s blog.

Habit #2: Default to writing commit messages in an editor

I don’t know about you, but I was definitely taught to use -m for writing commit messages. And although I’d seen vim pop open while merging branches, I hadn’t totally connected that you could get that behavior for every commit (or why you’d want to).

Now, unless I’m making a super trivial commit, I write commit messages in a full editor. When you drop the -m flag on the commit command, Git will open your default editor and prompt you to write a commit message there.

One benefit is that by default, you’ll see key details about the commit you’re about to make, like the current branch and a list of changed files. But also, congrats!—you’ve unlocked multi-line commit messages.

Not every commit needs detailed explanation, but some do. The first line will show up in the Git log, but you can add additional lines to include important context, like why you had to update a config file in a certain way, or how to interpret an obscure bug fix.

I’ve also found opening an editor slows me down enough to think of a clear, concise commit message. (Otherwise I might jot off something obscenely vague. We’ve all seen “Fixed stuff” in the log 😬)

This simple habit has helped me reframe what a good commit message looks like. You can take it even further with custom templates. And if you do adopt this workflow, take a look at Chris Beams’ post for some excellent commit message guidelines.


Both of these habits make it easier to follow the best practice of creating “small, meaningful commits.” A practice that’s great in theory and—in my experience—rarely manifests.

But wow Git becomes so much easier to work with when you do have small commits! Suddenly the log makes more sense. It’s easier to review PRs. And everything feels a little tidier and more intentional, which is always nice.

You also unlock a lot more of Git’s power. Most debugging commands and advanced merge strategies only become useful if your commits are sufficiently small. But that is a post for another day.

P.S. If you enjoyed this post, or have any thoughts/questions/feedback, don’t hesitate to reach out to me on Twitter!