Applying mailing list patches with 'git b4'


b4 helps improve the workflow for mailing list based Linux kernel development, but doesn't offer direct git integration. Let's whip up a 'git b4' alias.

It was created by Konstantin Ryabitsev and has become a very frequently used tool for me.

It supports a lot of different ways for interacting with the Linux Kernel mailing lists. Of these the b4 am subcommand is what I primarily use. This subcommand downloads all of the patches belonging to a patch series and drops them into a .mbox file. But! It doesn't apply them to the repository we're currently in, and herein lies the itch that I would like to scratch.

The inspiration for this post is the script that @stellarhopper authored and @widawsky pointed out to me.

The Good, the Bad & the Ugly

After first publishing this post, people on the twittersphere suggested some alternative approaches, and it would seem that there are three different approaches to creating an alias like this. Naturally my original idea is the ugly.

The Good

@gregkh suggested a really short and to the point approach, where b4 am simply pipes the .mbox file to git am. I think it is ideal in this specific case since it avoids most the complexity of writing git alias functions but at the same time doesn't require any external script files.

Alt text

As you can see the verbosity is really nice, and none of the b4 output is thrown out.

$ cat ~/.gitconfig
... snip ...
    b4 = "!f() { b4 am -t -o - $1 | git am -s; }; f"
... snip ...

The Bad

When @widawsky first linked the ~/bin/git-b4am script by @stellarhopper, it looked like a standalone shell script. This is not the case however, it is automatically integrated as a subcommand by git. As explained by @EnJens, git will present any executable accessible through $PATH/git-XXX as a subcommand git XXX.

Alt text

Using Zsh, I'm seeing some of the output being written after the command has returned. Using bash, this was less of an issue. I'd think this is due to the really neat way that processes substitution + tee is used, tee >(find_apply_mbx).

For the general case of running a script as a part of git, I think this is the way to go. The only downside to me is that the script is an external file.

$ cat ~/.local/bin/git-b4am
#!/bin/bash -eE

    mbx=$(awk '/^Writing .*\.mbx/{ print $2 }')
    if [[ $mbx ]]; then
        git am "$mbx"

b4 am -cls "$@" 2>&1 | tee >(find_apply_mbx)

The Ugly

Wanting to avoid the external scripts (and not knowing about $PATH/git-XXX functionality) I wrote a cursed version of the ~/bin/git-b4am script.

Alt text

As you can see, the helpful output from b4 is lost. This is due to git alias functions being executed in a sh shell, which doesn't support the really neat processes substitution approach that @stellarhopper had used.

I apologize in advance for the escaped hellscape that is this snippet. A hierarchy of escapes is required to conform to the git function syntax when using both multiple lines and quoted strings.

$ cat ~/.gitconfig
... snip ...
    b4 = "!f() \
        b4 am $1 -l -o /tmp/ 2>&1 | \n\
        $( \n\
            mbx=$( \n\
                awk '/^Writing .*\\.mbx/{ print $2 }' \n\
            );  \n\
            [ -z \"$mbx\" ] ||  \n\
                git am \"$mbx\" 1>&2; \n\
        );  \n\
    }; f"
... snip ...

A git syntax escape script written by Tom Hale made the escaping much easier.


After picking your favorite approach, go find the Message-Id for the LKML patch or series you want to apply.

$ cd linux
linux$ git b4 1607651182[email protected]

Tags: linux · kernel · development · shell · git · alias · b4 · gitconfig · mbox · am · mailing · list