Hunk editing with Magit

~779 words. ~3 minutes.

tags: git emacs tutorial

This was asked in a reddit post,

I want a separate commit for edits A, B, and C

Line 1 Line 2 editA Line 3 editB Line 4 editC Line 5

From the command line I do.

git add -p

git commit

That's hunk editing. Instead of untying an impossible knot you whack it apart with a machete (ie hunk edit).

Now with magit. I can select things in the status buffer with regions. But this falls apart when changes are entangled and not contiguous.

How do you do this in magit? Even vc doesn't support hunk editing. How can the ultimate editor in the pantheon of editors have overlooked hunk editing? Yeah I know you can set $editor to Emacs and edit hunks but I would like to master a 100% emacs workflow without switching to the terminal.

It is a bit confusing but their problem is that they want to only commit the Line 2 diff part. But they don't actually tell you how their diff looks like or what the original file was, if we are to make a reasonable guess, I would say their initial file looked like this.

line 1
line 2
line 3
line 4
line 5

And then they edited it to be like so,

line 1
line 2 editA
line 3 editB
line 4 editC
line 5

Now the diff looks something like this,

diff --git a/file b/file
index a751413..7ecd66d 100644
--- a/file
+++ b/file
@@ -1,5 +1,5 @@
line 1
-line 2
-line 3
-line 4
+line 2 editA
+line 3 editB
+line 4 editC
line 5
\ No newline at end of file

The first thing that comes to mind is actually quite naive; to simply mark the -line 2 region and then +line 2 editA region, one by one, but that approach actually leads to a difference like this.

diff --git a/file b/file
index a751413..7beac75 100644
--- a/file
+++ b/file
@@ -1,5 +1,5 @@
 line 1
-line 2
 line 3
 line 4
+line 2 editA
 line 5
\ No newline at end of file

The commit would ultimately look like this,

line 1
line 3
line 4
line 2 editA
line 5

The author of the Reddit post refers to it as, very confusingly, a 'corrupted commit', but it's not actually a 'corruption', rather it's simply not what was expected.

Thankfully, all you need to do to fix this is to simply type e on the staging area to open up Ediff. In the Ediff control buffer, type B to disable read-only mode for 'index', (which is essentially the thing you staged). Then happily edit the staging area to how you want it to be.

After doing that, I have this diff in the staging area,

diff --git a/file b/file
index a751413..4207b6e 100644
--- a/file
+++ b/file
@@ -1,5 +1,5 @@
 line 1
-line 2
+line 2 editA
 line 3
 line 4
 line 5
\ No newline at end of file

Which is what we need!

This is a very unusual operation that I frankly never needed to do before reading that post (Hence the confusion in the comment section). But yes, Magit can help you with this too.

Author: tusharhero

emailreplace [at] with @, and put the domain for username, and vice versa: sdf.org [at] tusharhero

© tusharhero 2024-2025, check licenses page for details.

Date: 2025-08-11 Mon 15:44

Site built at: 2025-08-11 Mon 07:07

Emacs 31.0.50 (Org mode 9.7.11)