Improve your commit hygiene with `git add — patch`

gjgd
Transmute
Published in
3 min readAug 14, 2019

--

At Transmute, as our engineering team transitioned to being fully remote, we found it helpful to leverage Git’s extensive version control features to stay updated with the team’s contributions. Specifically writing smaller and simpler commits made a huge difference to improve our review process and overall code quality. In this post, we’ll talk about how this small change in practice made a big difference for our team.

Small commits are beautiful

We noticed significant benefits by transitioning to writing smaller and smaller commits over the last few months:

  • Debugging is easier: For example, to use git-bisect to do a binary search on the commit history to find where a bug was introduced
  • Commit names are more accurate and can be used to automatically generate changelogs
  • Reviewing is easier since small commits are focused commits
  • Responding to a review is easier, with the use of git-revert
  • Developing a new feature is easier, by having an organized working directory

Git Staging Area is a powerful tool

A big part of learning how to write better, smaller commits is to learn how to use the staging area.

https://git-scm.com/book/en/v1/Getting-Started-Git-Basics

The typical way to move a change from the working directory to the staging area is using the git-add command. However, without any flags, this command only lets you stage entire files. That is not enough granularity if we have several unrelated changes in the same file that we want to commit separately. The solution is to use the --patch flag:

git add --patch

It separates all changes into hunks and lets you interactively choose which ones you want to stage and which ones you want to keep in the working directory. For each hunk, you have the following options:

y — stage this hunk
n — do not stage this hunk
q — quit; do not stage this hunk or any of the remaining ones
a — stage this hunk and all later hunks in the file
d — do not stage this hunk or any of the later hunks in the file
s — split the current hunk into smaller hunks
e — manually edit the current hunk
? — print help

This level of granularity is perfect to write smaller commits and improve code hygiene!

Note: To check the state of your staging area, use

git status # To see which files are in the staging area
git diff --cached # To see which changes are int the staging area

Let’s implement a new feature!

To see it in context, today you’re going to work on a new feature! Your mission, if you’re willing to accept it, is it implement the add function:

After an intense brainstorming session, and two cups of coffee later, the following implementation was chosen:

return a + b;

It passes the tests, awesome! But notice that a few things are wrong with the file:

  • subtract is missing documentation
  • There is a typo in multiply’s name
  • divide is lacking input validation

After careful refactoring, the file now looks like this:

You implemented the feature and improved the code, great job! Let’s push our changing to version control. Using git add --patch, we are able to select each hunk independently:

We end up with 4 small and separated commits:
* 792eb4f (HEAD -> master) Add input validation for divide operation
* acfb238 Fix typo for multiply operation
* 1c1f458 Add doc to subtract operation
* 6c28c5d Implement add operation

Those commits are explicit, easy to review, and if we need to revert one of them, we can do so very easily without any side effects!

What about you? What git command do you find useful to simplify your workflow, and have better commit hygiene?

--

--