One of the many versatile features of Git is the ability to partially commit edited files. If you make a bunch of edits to a file, but you only want to commit part of it, you can do so, and Git is pretty good about dividing changes in a file into disparate sections, or hunks. If you make changes on lines 5-10 and lines 40-50, then these will be two separate hunks within the file that can be staged and committed separately. Most GUI programs that interact with Git provide easy means to stage/unstage a hunk to give you more control over your commits.
But what if you make changes on lines 5-10 and 11-20? Git can sometimes create a single hunk out of multiple logical changesets (due to proximity). What can you do about that?
By getting your hands dirty using the Git command line of course!
Patch Mode
Typically, when you stage files for committing in Git, you write git add
or git stage
. Naturally, there are flags you can pass to this command to modify how it behaves. One such flag is -p
, or Patch Mode. This command will walk you through every hunk that is possible to stage, and prompt you with a plethora of options to take.
Let’s run git stage -p
on this blog post I’m writing right now and see what happens!
PS C:\Dev\nimblepros-blog-gatsby> git stage -p
diff --git a/content/blog/chunky-git-commits/index.md b/content/blog/chunky-git-commits/index.md
index 281da52..17ef7c3 100644
--- a/content/blog/chunky-git-commits/index.md
+++ b/content/blog/chunky-git-commits/index.md
@@ -1,10 +1,12 @@
---
-title: Dicing Up Git Chunks
+title: Dicing Up Git Hunks
author: scott
date: "2025-09-25T00:00:00.000Z"
-description: ""
+description: "Learn how to use the Git command line to fully control what parts of files you commit. Use the interactive Patch Mode to split hunks further to refine your commits."
featuredImage: ./chunky-git-commits.png
category: software-development
---
https://github.com/NimblePros/nimblepros-blog-gatsby/issues/371
+
+One of the many versatile features of Git is the ability to partially commit edited files. If you make a bunch of edits to a file, but you only want to commit part of it, you can do so, and Git is pretty good about dividing changes in a file into disparate sections, or *hunks*. If you make changes on lines 5-10 and lines 40-50, then these will be two separate hunks within the file that can be staged and committed separately. Most GUI programs that interact with Git provide easy means to stage/unstage a hunk to give you more control over your commits.
(1/1) Stage this hunk [y,n,q,a,d,s,e,p,?]?
Observe that it shows the whole file as a single hunk. The “title” and “description” lines of metadata were updated, and the first paragraph of the blog post was being typed out. It then asks whether to stage this hunk. If you type ?
it explains what all the options are:
(1/1) Stage this hunk [y,n,q,a,d,s,e,p,?]? ?
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
p - print the current hunk, 'P' to use the pager
? - print help
y
will stage it and n
will skip it. We’ll be focusing on the s
option to split the hunk up.
Spitting Hunks Into Smaller Hunks
Let’s try it, inputting s
to the prompt:
(1/1) Stage this hunk [y,n,q,a,d,s,e,p,?]? s
Split into 3 hunks.
@@ -1,4 +1,4 @@
---
-title: Dicing Up Git Chunks
+title: Dicing Up Git Hunks
author: scott
date: "2025-09-25T00:00:00.000Z"
(1/3) Stage this hunk [y,n,q,a,d,j,J,g,/,e,p,?]?
Git tells us that it split this single hunk into 3 hunks, and we can see that the title modification is now the only thing in this hunk. Now if I wanted to, for example, only commit the meta data, I would stage this hunk and the next one (which is just the description), and skip the last one.
My staged changes now only contain the metadata updates (git diff --staged
):
PS C:\Dev\nimblepros-blog-gatsby> git diff --staged
diff --git a/content/blog/chunky-git-commits/index.md b/content/blog/chunky-git-commits/index.md
index 281da52..def3687 100644
--- a/content/blog/chunky-git-commits/index.md
+++ b/content/blog/chunky-git-commits/index.md
@@ -1,8 +1,8 @@
---
-title: Dicing Up Git Chunks
+title: Dicing Up Git Hunks
author: scott
date: "2025-09-25T00:00:00.000Z"
-description: ""
+description: "Learn how to use the Git command line to fully control what parts of files you commit. Use the interactive Patch Mode to split hunks further to refine your commits."
featuredImage: ./chunky-git-commits.png
category: software-development
---
While my first paragraph is still unstaged (git diff
):
PS C:\Dev\nimblepros-blog-gatsby> git diff
diff --git a/content/blog/chunky-git-commits/chunky-git-commits.png b/content/blog/chunky-git-commits/chunky-git-commits.png
index fe611ac..aad9a78 100644
Binary files a/content/blog/chunky-git-commits/chunky-git-commits.png and b/content/blog/chunky-git-commits/chunky-git-commits.png differ
diff --git a/content/blog/chunky-git-commits/index.md b/content/blog/chunky-git-commits/index.md
index def3687..17ef7c3 100644
--- a/content/blog/chunky-git-commits/index.md
+++ b/content/blog/chunky-git-commits/index.md
@@ -8,3 +8,5 @@ category: software-development
---
https://github.com/NimblePros/nimblepros-blog-gatsby/issues/371
+
+One of the many versatile features of Git is the ability to partially commit edited files. If you make a bunch of edits to a file, but you only want to commit part of it, you can do so, and Git is pretty good about dividing changes in a file into disparate sections, or *hunks*. If you make changes on lines 5-10 and lines 40-50, then these will be two separate hunks within the file that can be staged and committed separately. Most GUI programs that interact with Git provide easy means to stage/unstage a hunk to give you more control over your commits.
Nice!
Full Power: Manually Editing Hunks
Sometimes, Git cannot automatically split hunks down any further. Consider the following hunk:
- <PackageVersion Include="foo-package" Version="1.0.0" />
- <PackageVersion Include="bar-package" Version="4.8.0"/>
+ <PackageVersion Include="foo-package" Version="2.0.0" />
+ <PackageVersion Include="bar-package" Version="4.8.0" />
Trying the split command (s
) resulted in no changes:
(1/1) Stage this hunk [y,n,q,a,d,e,p,?]? s
Sorry, cannot split this hunk
(1/1) Stage this hunk [y,n,q,a,d,e,p,?]?
Let’s say we only wanted to commit the version upgrade and ignore the whitespace fix. What do we do? Use the Manual Edit command, e
!
This will pop open a text editor with the full hunk inside. I made a quick dummy edit to this blog post and loaded it up:
# Manual hunk edit mode -- see bottom for a quick guide.
@@ -121,3 +121,9 @@ index def3687..17ef7c3 100644
```
Nice!
+
+Foo Foo Foo
+
+Bar Bar Bar
+
+ajskdfjasdk jfdsajfasdkj fdsak
# ---
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
# If the patch applies cleanly, the edited hunk will immediately be marked for staging.
# If it does not apply cleanly, you will be given an opportunity to
# edit again. If all lines of the hunk are removed, then the edit is
# aborted and the hunk is left unchanged.
Important takeaways:
- To exclude a deletion line (
-
), change them to - To exclude an addition (
+
line) from a hunk, delete it (don’t just leave the line blank; remove the whole line). - After exiting the editor, the hunk will automatically be staged and the Interactive Mode will continue.
From my example above, the below hunk will stage the “foo” line, not stage the “bar” line, and stage a deletion of the keyboard-mash line.
+
+Foo Foo Foo
+
+
-ajskdfjasdk jfdsajfasdkj fdsak
Running git diff --staged
will then show that only the changes I explicitly staged will be added. Cool!
A Rare Tool, but a Useful One
I wager I have to drop down to Git’s Interactive Mode less than 1% of the time I’m doing a commit. The majority of the time when I’m working with parts of a file, Git’s automatic splitting does the job. Like with most tools in our command line toolbelt, however, it’s always nice to have it available when needed!