When maintaining a project sooner or later there comes the time when you need to
apply patches that have been submitted to you. Assuming a patch-based workflow
those are going to be one patch per mail, possibly connected in a thread.
There's lots of different ways of getting those patches to their final
git-am(1), and in this post I
want to take a look at ones that work well with
neomutt(1) since that is what I use.
I want to rely on the default bindings as much as possible. All mentioned
bindings should work out of the box.
Applying a single patch is very straightforward: Select the mail in the pager
| to pipe it to an external command. This command will be some
git am -s to also add a
What if you want to apply a patch series, however? An obvious solution would be
to pipe each message in the thread to
we invoked earlier with
| only applies to the currently selected message, so
we can't use that on the whole thread. Instead we can tag the whole thread using
<Esc>t, then use the
; followed by
| to send all
tagged messages to
There's two problems with this, though. The first is that depending on the setting
git-am(1) might only apply the first patch in the series. This is the case if
pipe_split is set to the default of
mutt(1) will then concatenate the
messages before sending them to the external command. Sadly this concatenated
format is slightly different from the
mbox format that
making it not see anything past the first patch.
pipe_split set to
mutt(1) spawns one process per tagged mail
instead, applying all patches correctly. Now that
git-am(1) is spawned once
per mail, however, you lose its atomicity: Neither
ORIG_HEAD will be set
correctly, nor will
--abort go back to the original branch.
This might not be a big issue, but I am not a fan. Thankfully
supports reading patches from
mbox files or
Maildir structures. So instead
of piping mails to
<pipe-message>, let's save them to the
current directory: With the thread still tagged,
<copy-message>) will save a copy of it under a given path. Now you can
apply the series by hitting
! and running
git am -s <path>. This works with
mbox_type set to
Maildir (but see № 9
Of course there is no need to rely on the default bindings, especially if you
need to do this kind of thing very often.
mutt(1) is easily customizable,
making it possible to bind the entire chain of actions to just one keystroke.
If you're interested in a more detailed examination of a patch-based workflow
mutt(1), check out this
by Greg Kroah-Hartman.