• Skip to primary navigation
  • Skip to main content
Sal Ferrarello
  • About Sal Ferrarello
  • Speaking
  • Connect
    Mastodon GitHub Twitter (inactive)
You are here: Home / Dev Tips / Add git status to zsh prompt

Add git status to zsh prompt

Last updated on December 29, 2020 by Sal Ferrarello

One of the things that made me much better at Git was making my current branch (and whether or not I have any changed files) always visible. By default zsh includes everything you need to do this, you just need to configure it.

zsh prompt with modified git status from vcs_info.

Quick Solution

The short answer is to add this block of code to the bottom of your ~/.zshrc file. This will use functionality already built into zsh to display your Version Control System information (which includes Git) in your prompt.

After adding these lines, you’ll need to start a new terminal session – you can do this by closing your terminal and opening it again.

# Autoload zsh add-zsh-hook and vcs_info functions (-U autoload w/o substition, -z use zsh style)
autoload -Uz add-zsh-hook vcs_info
# Enable substitution in the prompt.
setopt prompt_subst
# Run vcs_info just before a prompt is displayed (precmd)
add-zsh-hook precmd vcs_info
# add ${vcs_info_msg_0} to the prompt
# e.g. here we add the Git information in red  
PROMPT='%1~ %F{red}${vcs_info_msg_0_}%f %# '

# Enable checking for (un)staged changes, enabling use of %u and %c
zstyle ':vcs_info:*' check-for-changes true
# Set custom strings for an unstaged vcs repo changes (*) and staged changes (+)
zstyle ':vcs_info:*' unstagedstr ' *'
zstyle ':vcs_info:*' stagedstr ' +'
# Set the format of the Git information for vcs_info
zstyle ':vcs_info:git:*' formats       '(%b%u%c)'
zstyle ':vcs_info:git:*' actionformats '(%b|%a%u%c)'

The rest of this article will go into these settings and how they work.

Default Prompt

By setting the environment variable PROMPT you can define the information zsh should display on the command line prompt. My default prompt looked something like this

zsh default prompt.

You can view your settings for PROMPT by running the following from the command line.

echo $PROMPT

If you are using the default zsh prompt this will output

%n@%m %1~ %#

The %n, %m, and %# are all zsh prompt sequences which get expanded into “username”, “hostname”, and % (or # when logged in as a super user account like root).

zsh add-zsh-hook

add-zsh-hook is a built in function that comes with zsh. You can use this function to run other functions at certain pre-determined times.

Autoloading add-zsh-hook

By default, zsh does not load add-zsh-hook. If we want it to be available, we need to add the following to ~/.zshrc

autoload -Uz add-zsh-hook
  • -U mark the function for autoloading and suppress alias expansion
  • -z use zsh style for function

See zsh function information for more information on functions and autoloading.

zsh vcs_info

vcs_info is a built in function that comes with zsh. You can use this in your zsh prompt by adding the following to your ~/.zshrc file. (If you want to see the code inside the vcs_info function, you can run the following at the command line declare -f vcs_info).

Autoloading vcs_info

By default, zsh does not load vcs_info. If we want it to be available, we can add it to our autoload statement we are already using for add-zsh-hook in ~/.zshrc

autoload -Uz add-zsh-hook vcs_info

Enable Substitution in the PROMPT

zsh will allow you to use an environment variable in your prompt. Using the format ${variable_name} but this functionality is off by default. We need to enable it with

setopt prompt_subst

We do this because our Git information is going to be stored in an environment variable (vcs_info_msg_0_) and we’re going to add this variable to our prompt.

Run vcs_info before displaying the prompt

Here we use the zsh hook function precmd to run the vcs_info function right before we display the prompt. When this function runs, it gathers information about Git for the current directory and puts this information in the environment variable vcs_info_msg_0_.

add-zsh-hook precmd vcs_info

Modify PROMPT

Finally after all this configuration, the result of vcs_info is stored in vcs_info_msg_0 and we add this to our prompt with ${vcs_info_msg_0_}

PROMPT='%1~ %F{red}${vcs_info_msg_0_}%f %# '

In this case we’ve also wrapped the string in %F{red} and %f to set ${vcs_info_msg_0_} to red.

zsh prompt with git status using vcs_Info.

Have vcs_info check for Git changes

By default, vcs_info does not check for changes (staged or unstaged) because we want to include this information in our prompt we set the vcs_info check-for-changes to true.

zstyle ':vcs_info:*' check-for-changes true

This is a vcs_info configuration option.

Modify the Strings Indicating Changes

By default U and S are used respectively for unstaged and staged changes when the %u and %c placeholders are used. We change these symbols to * and + respectively by setting these vcs_info configuration options.

zstyle ':vcs_info:*' unstagedstr ' *'
zstyle ':vcs_info:*' stagedstr ' +'

Set the Git Format of vcs_info

In the same way we can define the format for a prompt (using % sequences) we can set the format for vcs_info. The vcs_info function supports multiple types of Version Control System (VCS), we are only interested in Git at the moment so we target vcs_info:git.

zstyle ':vcs_info:git:*' formats       '(%b%u%c)'
zstyle ':vcs_info:git:*' actionformats '(%b|%a%u%c)'

There are two formats to set:

  • formats used for the default “vcs_info” string
  • actionformats used when the prompt is displayed and Git is in the middle of an action (like rebase, merge, or cherry-pick)

The sequences used here are:

  • %b the current branch name
  • %u are there any unstaged changes
  • %c are there any staged changes
  • %a the current Git action being performed (this only makes sense in actionformats)

zsh prompt with modified git status from vcs_info.

Sal Ferrarello
Sal Ferrarello (@salcode)
Sal is a PHP developer with a focus on the WordPress platform. He is a conference speaker with a background including Piano Player, Radio DJ, Magician/Juggler, Beach Photographer, and High School Math Teacher. Sal can be found professionally at WebDevStudios, where he works as a senior backend engineer.

Share this post:

Share on TwitterShare on FacebookShare on LinkedInShare on EmailShare on Reddit
Warning! This is a draft, not a finalized post. See full draft disclosure.

Filed Under: Computing, Dev Tips, Draft, Recommendations, Solution Tagged With: command line, Git, zsh

Reader Interactions

Comments

  1. Steve says

    December 17, 2020 at 4:23 pm

    Love that you did and how you explained what the code you were adding to the .zshrc does. Probably a subconscious action from the Math Teacher in you.
    I learned stuff, thank you!

    Reply
  2. Danny says

    December 29, 2020 at 8:44 am

    Thanks for the example.
    I have a question though. I change the prompt to this:

    PROMPT=’%1~ %F{red}${vcs_info_msg_0_}%f ‘

    But what I don’t get is that when I’m not in a git context I see this:
    somedir [user@compname]$

    I can’t figure out where this ‘[user@compname]$’ comes from.

    Any idea?

    Cheers,
    Danny

    Reply
    • Danny says

      December 29, 2020 at 9:00 am

      Mm.. nevermind.. after a new terminal session, this no longer seems to be the case

      Reply
      • Sal Ferrarello says

        December 29, 2020 at 12:59 pm

        Thanks for pointing this out, Danny. I’ve added a note about starting a new terminal session to this blog post. Thanks.

        Reply
        • bas says

          March 5, 2021 at 10:05 am

          Or you can run the command
          source ~/.zshrc

          Reply
  3. Afrid says

    July 17, 2021 at 2:23 pm

    How to know that there are untracked files (after changes or after creating new files)

    Reply
  4. Chris says

    December 8, 2022 at 6:54 pm

    Thank you for this article. The best explanation I’ve found about this subject.

    Reply
  5. Ryan Neilson says

    March 3, 2023 at 3:59 pm

    For developers using bash, you can use something like the following in your .bashrc file in order to see the highlighted name of your current git branch in the terminal:

    parse_git_branch() {
    git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/'
    }
    export PS1="\u@\h \[\e[32m\]\w \[\e[91m\]\$(parse_git_branch)\[\e[00m\]$ "

    You’ll need to exit any open terminal windows after making the change in order for it to be seen.

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Copyright © 2023 · Bootstrap4 Genesis on Genesis Framework · WordPress · Log in