I recently started using git’s patch mode via git add -p
. Patch mode makes my commits more granular, which means my commit messages are more accurate. Better still, patch mode allows you to abstract away from adding “files” – you’re adding changes to be committed. This is a closer mental model to what git is actually doing. I’m finding it particularly useful for code review: make several changes in a friend’s program, group the changes by concept, and commit one concept at a time.
That’s the why – here’s the how.
git add -p
launches what git calls the “interactive hunk selector.” This leads me to my other favorite reason to use -p: besides being useful, all the docs sound like an episode of The Bachelorette. “Once you have decided the fate of all the hunks, if there is any hunk that is chosen, the index is updated with the selected hunks.” And if not, our bachelorette takes the million dollars!
In practice, I only end up using three of the interactive hunk selector options: [y]es, [n]o, and [s]plit. Split takes the current hunk and divides it into smaller hunks, then presents them for selection one at a time. (If you’re attempting to continue the Bachelorette metaphor, now is a good time to stop.)
Let’s look at an example. Suppose I’m working on a function that recursively calculates the sum of element of a list. My first draft looks like this:
1 2 3 4 5 6 |
|
Not bad, but it’s a little verbose. Let’s take advantage of the fact that an empty list is falsey. And, oops, we’re overwriting the built-in sum
function in python – we probably don’t want to do that.
1 2 3 4 5 6 |
|
Ok, these are two different thoughts, but we didn’t commit in between. Interactive mode to the rescue – let’s stage those hunks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Our changes aren’t in the right hunks, so we’ll pick s
to split them.
1 2 3 4 5 6 7 |
|
Let’s deal with the naming issue first. y
. Next up:
1 2 3 4 5 6 |
|
This one’s different. n
.
1 2 3 4 5 6 |
|
Back to the naming issue. y
.
1 2 3 |
|
Now we can repeat this process for our other change.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
This is our only hunk now, so y
.
1 2 3 |
|
Of course, you may not want your commits to be quite this granular – but hopefully the example has demonstrated the strength of git add -p
in creating single-concept commits.