Let’s say we’ve just changed some CSS in a file and we want to stage it with Git. You might do something like this:
git add styles.css
…and then we’d want to make a commit with that staged code:
git commit -m "Fixed the CSS"
I’ve been doing this for a long time, but there’s lots of problems with this approach. For one, what happens if you changed more than one thing in `styles.css`? Perhaps we changed the borders of an element and then we changed the background color of an element that’s completely unrelated to the first. Well, it’s going to be very difficult to understand the history of our commits if we run
This is where Git’s patch mode comes in. It’s a thoroughly helpful flag that lets us split parts of a file so that we can stage and commit each part separately.
git add -p styles.css
Once we run that command we should see something like this:
We’ve made two changes on two separate elements, but there are all sorts of commands that we can run on something called a “hunk”. What we see here is one part of the codebase, or one hunk, but to see what all these commands mean we can just type
?. This will list all of the commands for us:
In this case, our two changes that we’ve made are currently part of the same hunk, so we’ll need to split them by typing
Now we can see that only the changes on the
.table class have been selected, which is precisely what we wanted. Then all we have to do is type
y to stage that hunk. However, git will give us the option to stage more hunks which is useful when we make similar changes to different parts of the codebase. Yet in this situation we just want to quit out of this process so we’ll need to run
This all makes more sense when we type
git status into the command line; we’ll see that we’ve added some code from styles.css and if we run
git diff styles.css we’ll see that only one line of CSS has been staged:
All that’s left is to make the commit whilst making sure we write something memorable for future reference, such as:
git commit -m "fixed the border of the form"
This way we can scan through our commit history and understand it all much more easily.
Yay for Git’s patch mode!
Great post! I’m already seeing great ways to use it. I freaking love git!
Same goes for stashing btw :)
git stash -p
Nice! Thanks for the tip, it will be really helpful for me.
Very useful techniques, and nice to see it described at the command-line level. Works much the same way in tools like SourceTree (which I highly recommend!).
I second the SourceTree recommendation. The semi-graphical display of the hunks is very easy to understand and choose which hunk(s) you want to stage or discard. You can also change the size of most hunks (similar to the
scommand in this article’s example) by changing the “number of lines of context” dropdown just above the diff panel.
Yeah, I published very similar post some time ago. https://pawelgrzybek.com/git-tip-staging-hunk-of-code-via-command-line/ After doing this for a while, I need to admit that whenever I need to split commit I’m lunching my favourite GUI git client – Tower 2 (which is currently 25% off, worth to have a look: https://www.git-tower.com/). Thanks
Your post is actually much clearer :-)
I used to switch to third party clients like SourceTree to do this. Now I can do it in the command line. Great!
I moved from command line to Source Tree a few months ago and noticed this a few weeks ago. I assumed it was a Source Tree only feature.
All of my commits have been made using patch for quite some time. Another great thing, is that it lets you see what you are actually commiting, you can see your console.log(), leftover comments, messy whitespace, etc.
Awesome post!! Makes things so much more organized and delineated!
On Mac, Gitx makes this really easy – it’s more lightweight than sourcetree and also open source (no Atlassian account required!)
The original is dead but the gitx-dev fork is more up to date.