2020-06-21

Writing a Zsh prompt that shows git branches

2020-11-14: Adding compatibility for older git versions.

Zsh is a great shell which offers more customization options than the bash shell that is standard on most systems. There are a lot of ready made themes out there, which include the features I’m going to talk about. If you’re still interested in learning about Zsh’s prompt expansion and how to customize the command line prompt on your own, read on:

1 Zsh Prompt with git branch

The example I want to use to explain the customization options af Zsh is a prompt that shows the following information:

Customized prompt (of course with your username instead of monti)

The code below includes all the functionality. Zsh comes with built-in features to show the current user, the time or the working directory. Showing the current git branch is possible by executing arbitrary commends as the prompt is shown.

# append to ~/.zshrc
setprompt() {
  setopt prompt_subst
  PROMPT='%~ | %B%F{cyan}%n%b%f$(
    git rev-parse --is-inside-work-tree &> /dev/null \
    && echo -n " | " \
  && git rev-parse --abbrev-ref HEAD) $ '
  RPROMPT='%D{%H:%M:%S}'
}
setprompt

Just append this to your ~/.zshrc and you should see the prompt shown above. How this commands makes up the prompt is explained in the rest of this article.

2 Zsh Prompt Expansion

(Zsh’s documentation gives an overview of the different escape parameters)

Customizing a zsh prompt works by assigning a string to the variables PROMPT (normal prompt on the left side of the screen) and RPROMPT (prompt on the right side of the terminal). Zsh comes with a large number of predefined parameters that can be used in a prompt and that will be replaced to show other information.

2.1 Basic Prompt Escape Sequences

A very basic example is the parameter %n which, when used in a prompt definition, will be replaced by the username.

I set the prompt on the right side of my terminal to show the current time: RPROMPT='%D{%H:%M:%S}'.

%D will be escaped to show the current time when updating the prompt and the following brackets can contain an optional format string as known from the strftime function.

2.2 Including Commands in the Prompt

It’s worth looking through the documentation because Zsh offers a lot of features out of the box. However, this list doesn’t include a way to show information like the checked out git branch in the working directory. But since Zsh also allows to run arbitrary commands in the prompt, we still can achieve this.

My prompt first checks whether the current working directory is inside a git repository (git rev-parse --is-inside-work-tree &> /dev/null). This command outputs some error msg if the folder isn’t part of a git repo and true if it is. But since we’re only interested in the return value of the program and not in displaying an error message, all output is redirected to /dev/null, so nothing will be printed.

Instead we’re going to print a delimiter | and the current branch if the command runs successfully (i.e. if the current directory is part of a git repository - more on that in the last section of this page). This is done by using cmd1 && cmd2 which basically will execute cmd2 only if cmd1 succeeds. This way the branch information is only printed if the working directory is a git repository.

All of this is enclosed in $( ... ) to make the prompt execute the commands inside the brackets.

3 Styling with Text Attributes

In addition to sequences that will be replaced by other information there is also the option to set text attributes like font weight or color. %F{color} starts applying a color to the following text and %f will make the parser stop using this color. %B and %U will change the text to bold or underlined, respectively, while %b and %u will stop applying these effects to the text that follows them.

There are still more options which can be found in Zsh’s documentation which I linked above.

But in the end, the prompt is less important than the output it’s showing so don’t spend too much time with customizing your prompt :D

4 A Note on git Versions

In the example above I used the command

git rev-parse --abbrev-ref HEAD

to show the current git branch. This will also work for older git versions.

Users of git 2.22 or newer can also go with this command:

git branch --show-current

Ubuntu 18 still comes as standard with git 2.17.1, so the latter one won’t work. You can get the version that is installed on your system by executing

git --version