Hunk editing with Magit
~779 words. ~3 minutes.
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.