+++ date = 2021-07-23T22:37:17+02:00 title = "Applying patches with mutt(1)" [taxonomies] tags = ["git", "TIL"] [extra] related = [9] +++ 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 destination, [`git-am(1)`](https://git-scm.com/docs/git-am), and in this post I want to take a look at ones that work well with [`mutt(1)`](http://mutt.org/) or [`neomutt(1)`](https://neomutt.org/) 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 and hit `|` to pipe it to an external command. This command will be some variation of `git-am(1)`, perhaps `git am -s` to also add a `Signed-off-by` trailer. What if you want to apply a patch series, however? An obvious solution would be to pipe each message in the thread to `git-am(1)`. The `` command 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 `t`, then use the `` command `;` followed by `|` to send all tagged messages to `git-am(1)`. There's two problems with this, though. The first is that depending on the setting of [`pipe_split`](https://neomutt.org/guide/reference#3-280-%C2%A0pipe_split), `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 `no`; `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 `git-am(1)` expects, making it not see anything past the first patch. With `pipe_split` set to `yes`, `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 `git-am(1)` supports reading patches from `mbox` files or `Maildir` structures. So instead of piping mails to `git-am(1)` via ``, let's save them to the current directory: With the thread still tagged, `;C` (`` followed by ``) will save a copy of it under a given path. Now you can apply the series by hitting `!` and running `git am -s `. This works with [`mbox_type`](https://neomutt.org/guide/reference#3-188-%C2%A0mbox_type) set to either `mbox` or `Maildir` (but see {{ ref(id=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 with `mutt(1)`, check out this [post](http://kroah.com/log/blog/2019/08/14/patch-workflow-with-mutt-2019/) by Greg Kroah-Hartman.