zsh: Add the name of current git branch to any command

Chris Perry
4 min readMar 17, 2022
Such alias. Much wow.

Here’s how to grab the name of your local git branch for reference in other commands, particularly aliases.

For macOS users, the end solution looks like this (GNU Linux users, change ggrep to grep). Add to your .zshrc:

## Capture name of current git branch
autoload -Uz vcs_info
precmd() { vcs_info }
gitBranch="$(echo ${vcs_info_msg_0_} | ggrep -Pio '(?<=\(git\)-\[).*(?=\]-)')"
## Diff current branch against upstream/master
alias dum="git difftool ${gitBranch} upstream/master -- ':!package-lock.json' ':!package.json'"

Addendum for macOS users: In order for this command to work, you’ll need to install GNU grep. To do this, run:

brew install grep

Wait… what in the name of the gods did I just read?

My coworker, Josh Avery, challenged me to expound on my answer above, which was the entirety of the original article as published.

Here’s what I’ll say as a preamble… don’t be afraid of the command line! It’s really pretty simple and straightforward, in its own arcane sort of way.

Let’s get into it line-by-line.

autoload -Uz vcs_info

According to dev blogger Arjan van der Gaag, you’re not cool if you don’t display some Git status information in your prompt.

He goes on to explain:

vcs_info is a function that populates a variable for you. This variable can then be used inside your prompt to print information. What information is printed can be controlled by some configurations – which are essentially format strings.

Another answer comes from Mark Reed via StackOverflow, ‘What does autoload do in zsh?’:

Zsh comes with a bunch of standard functions in the default $FPATH already. But it won't know to look for a command there unless you've first told it that the command is a function.

That’s essentially what autoload does: it says "Hey, Zsh, this command name here is a function, so when I try to run it, go look for its definition in my FPATH, instead of looking for a command in my PATH."

In the same answer, cdarke explains:

The -U means mark the function vcs_info for autoloading and suppress alias expansion. The -z means use zsh (rather than ksh) style. See also the functions command.

More information on autoloading is available from the zsh documentation.

precmd() { vcs_info }

According to the zsh docs (‘Functions’):

precmd

Executed before each prompt. Note that precommand functions are not re-executed simply because the command line is redrawn, as happens, for example, when a notification about an exiting job is displayed.

Elsewhere from the zsh docs (‘Gathering information from version control systems’):

In a lot of cases, it is nice to automatically retrieve information from version control systems (VCSs), such as subversion, CVS or git, to be able to provide it to the user; possibly in the user’s prompt. So that you can instantly tell which branch you are currently on, for example.

In order to do that, you may use the vcs_info function.

gitBranch=”$(echo ${vcs_info_msg_0_} | ggrep -Pio ‘(?<=\(git\)-\[).*(?=\]-)’)”

This is where the boilerplate ends and the fun begins. There’s a lot to unpack here, so let’s go step-by-step with a review of the mechanics:

echo

The terminal’s OG version of console.log() or print() or whatever. More technically, it “writes arguments to the standard output,” accepting 1 or more space-separated arguments following the command itself.

grep

Short for “global regular expression print,” it searches plain-text datasets for lines that match a regular expression; invented by one of the founding fathers of modern computing, Ken Thompson. (See the legend of ‘grep’ as told by Brian Kerhnighan.)

Grep made its public debut in the manual for Unix Version 4 (c. 1973). In later Unix notes it was chronicled:

Grep, generally cited as the prototypical software tool, was born when Ken Thompson was asked how to search for patterns in a file that was too big for the editor. Thompson promptly liberated his regular expression recognizer and christened it after the ed command g/re/p. It was an instant hit and soon entered our language as a verb.

According to Thompson himself, the command originated “sometime before the 4th edition.”

${vcs_info_msg_0_}

The name of your local git branch, but with some crap around it. Outputs something like:

(git)-[my-current-branch]-

ggrep

macOS users only. It’s the global namespace reserved when you install GNU grep via brew install grep. Required to use regex capture groups.

${vcs_info_msg_0_} | ggrep

This segment is part of a line that includes the command echo, but you’ll notice that when it executes it doesn’t print or log anything.

That’s because in order for grep to work, it needs to grep from something. By starting the line with echo, a data stream begins, getting marshalled into grep by a method known as piping.

According to GeeksforGeeks:

Pipe is used to combine two or more commands, and in this, the output of one command acts as input to another command, and this command’s output may act as input to the next command and so on. It can also be visualized as a temporary connection between two or more commands/ programs/ processes.

In layman’s terms, the echo command from the left side then gets piped (via |) into the grep on the right side.

-Pio

Modifiers for ggrep:

  • -P enables capture groups
  • -i ignores case
  • -oonly captures the matching part of the expression

‘(?<=\(git\)-\[).*(?=\]-)’

A regex expression that captures all characters in between (git)-[ and ]-.

Putting it all together

  • autoload -Uz vcs_info: Load up a zsh-flavored serving of my version control system, using ‘vcs_info’ as a function definition and not as a file path
  • precmd() { vcs_info }: Do this before each command
  • gitBranch=”$(echo ${vcs_info_msg_0_} | ggrep -Pio ‘(?<=\(git\)-\[).*(?=\]-)’)”: Assign the name of my current local git branch to the variable ‘gitBranch’

That’s all there is to it! Thanks for reading o7

--

--