Locally re-pulling a Blender patch

A Fish shell function I use to re-fetch a Blender patch from developer.blender.org

As core developer of Blender I often review patches from colleagues and other contributors. Getting that patch on my local machine is as easy as typing arc patch D1234, where D1234 is the patch number. Once the author of the patch has updated it according to the feedback of the reviewers, it’s not as trivial to update my local copy of the patch, though. This involves:

git checkout master
git branch -D arcpatch-D1234
arc patch D1234

Without deleting the branch, Arcanist will, instead of updating the existing one, make a new branch for the patch.

So, as usual, I wrote a little Fish shell script to do this work for me. Fish shell? Yeah. After I posted my ZSH configuration, a friend of mine pointed me to the Fish shell. It took a bit of getting used to, but now I’m hooked, and I use it wherever I can. I might write another blog post about that some time.

UPDATE (2021-02-01): I’ve added optional rebasing on top of master to the commands. Just press ENTER to rebase, or Ctrl+C to skip that step and keep the branch as-is.

function git_rebase_onto_master
    read -P "Rebase onto master? ENTER for yes, CTRL+C for no."
    git rebase master && git submodule foreach git pull --rebase origin master
end

function arcpull -d "Refresh and reapply the current patch from Phabricator"
    set BRANCH (git branch --show-current 2>/dev/null)
    if [ -z "$BRANCH" ];
        echo "Not on a Git repo"
        return 42
    end

    set PATCHNUM (string replace arcpatch-D '' $BRANCH)
    if [ $BRANCH = $PATCHNUM ];
        echo "Current branch $BRANCH is not an arcpatch branch" >&2
        return 47
    end
    echo "Current branch $BRANCH is for patch $PATCHNUM"

    git checkout master
    git branch -D $BRANCH
    arc patch D$PATCHNUM
    git_rebase_onto_master
end

Now all I have to do is type arcpull and it’ll figure out which patch the current branch is for, and get a fresh copy for me.

UPDATE: I’ve added another command to the script: arcpatch D1234. This nukes the arcpatch-D1234 branch if you have it, and re-fetches the patch. It’s basically a version of the script above, except that it doesn’t take the D-number from the current branch but from the CLI argument.

function arcpatch -a PATCHNAME -d "Apply a patch from Phabricator"
    if test -z "$PATCHNAME";
        echo "Usage: arcpatch D1234" >&2
        return 47
    end

    set BRANCH arcpatch-$PATCHNAME

    set CURBRANCH (git branch --show-current 2>/dev/null)
    if test "$CURBRANCH" != "master";
        git checkout master
    end

    if git branch | grep -q $BRANCH;
        printf "\033[95mBranch $BRANCH exists, going to refresh it\033[0m\n"
        git branch -D $BRANCH
    else
        printf "\033[96mBranch $BRANCH does not exist\033[0m\n"
    end
    arc patch $PATCHNAME
    git_rebase_onto_master
end

UPDATE 2: another command to simply remove all arcpatch-Dxxxx branches:

function arcprune -d "Delete all arcpatch-Dxxxx branches"
    set BRANCHES (string trim (git branch | grep arcpatch-D))
    if test -z "$BRANCHES";
        echo "No arc branches to prune"
        return 0
    end
    echo git branch -D $BRANCHES
end

This post was made possible by the Blender Development Fund.

dr. Sybren A. Stüvel
dr. Sybren A. Stüvel
Open Source software developer, photographer, drummer, and electronics tinkerer

Related