Home | Posts by Category

One call Git status for your shell prompt

There are a million projects that retrieve status info from Git and reformat it for use in a shell prompt (1, 2, 3). Git itself even ships with one. Zsh has an excellent built-in system called vcs_info that I’ve contributed to and written about before.

The way these scripts usually work is to invoke Git many times in order to retrieve all the information you might want in your shell prompt – branch, current SHA, staged/unstaged files, whether your working directory is dirty, and the number of commits ahead or behind the remote-tracking branch. They often invoke Git half-a-dozen times or more but it doesn’t matter because Git is so fast you won’t notice the delay while the shell is drawing your prompt. In contrast Mercurial, using Python, hasn’t always enjoyed that same fast start-up and needed performance tricks to avoid slowing your shell prompt.

There was an addition to Git in 2016 that adds –porcelain=v2 to the git status command to fetch more of this information on a single invocation. Git is already fast but better efficiency is better :). Plus the output format is a delight to work with.

git \
    --no-optional-locks \
    status \
    --porcelain=v2 \
    --branch

The --no-optional-locks flag is useful for a shell prompt since it’ll be running Git often, sometimes while something else is also running Git, and you can occassionally see lock errors.

With a little awk you can quickly ingest all that output to reformat it into a prompt:

/^# branch\.oid/ { sha=substr($3, 0, 12) }
/^# branch\.head/ { branch=$3 }
/^# branch\.upstream/ { upstream=$3 }
/^# branch\.ab/ {
    a = $3 != "+0" ? $3 : ""
    b = $4 != "-0" ? $4 : ""
}
/^\?/ { untracked="?" }
/^[0-9] [A-Z]. / { added="A" }
/^[0-9] .[A-Z] / { modified="M" }
/^u UU/ { conflicts="UU" }

END {
    print (\
        sha,
        conflicts \
        added \
        modified \
        untracked ,
        branch \
        a \
        b)
}

I wrote one as a custom git prompt script to use tmux or ansi color escapes:

git-prompt script

A single invocation and a simple, straightforward parse is much nicer than what we’ve had to do in the past.