git branch in shell prompt

I’ve used this prompt for quite some time but realized I never blogged about it 🙂

As a git user I tend to work in a few branches at a time. Unlike subversion where you typically have a separate directory for each branch, with git branches update the working directory. So it is easy to get lost when you have more than one branch. Sure you can do

git branch

and

git branch -r

but this can be invasive when you could easily glance at your shell prompt.

In bash (is there really any other shell?), I updated my prompt to show the current branch:

PS1="[\u@\h \W\$(git branch 2> /dev/null | grep -e '\* ' | sed 's/^..\(.*\)/{\1}/')]\$ "

This make the prompt look like this:

[jmrodri@firebird sm-photo-tool{master}]$ 

7 thoughts on “git branch in shell prompt

  1. Just wondering: every time the shell shows the prompt, git branch gets executed?

    That’s the main reason I don’t like to mess too much with the shell prompt, but I may be wrong…

    1. Not just ‘git branch’ – also ‘grep’ and ‘sed’. Three fork/execs per prompt. Blarg!

      String manipulation inside bash isn’t too hard. You can do something like:

      function git_branch_for_cwd() { b=$(git symbolic-ref HEAD 2>/dev/null); [ “$b” ] && echo “{${b##*/}}”; }
      PS1=”[\u@\h \W\$(git_branch_for_cwd)]\$ ”

      which at least drops the grep and sed. (echo is a shell builtin, so no fork/exec there).

      But yeah. Try git-completion, where someone’s already done the work for you.

      1. Hi wwoods,

        That’s nice, in some environments it’s not possible to get git-completion installed (easily) and it’s good to see a lightweight solution using the extant tools.

  2. I use PS1='[\u@\h \W$(__git_ps1 “(%s)”)]\$ ‘

    and then with the bash_completion stuff for git that provides the __git_ps1 function.
    the bash_completion git file (which gives a whole slew of fun stuff) should be in the git source under contrib or something.

    __git_ps1 ()
    {
    local g=”$(git rev-parse –git-dir 2>/dev/null)”
    if [ -n “$g” ]; then
    local r
    local b
    if [ -d “$g/rebase-apply” ]
    then
    if test -f “$g/rebase-apply/rebasing”
    then
    r=”|REBASE”
    elif test -f “$g/rebase-apply/applying”
    then
    r=”|AM”
    else
    r=”|AM/REBASE”
    fi
    b=”$(git symbolic-ref HEAD 2>/dev/null)”
    elif [ -f “$g/rebase-merge/interactive” ]
    then
    r=”|REBASE-i”
    b=”$(cat “$g/rebase-merge/head-name”)”
    elif [ -d “$g/rebase-merge” ]
    then
    r=”|REBASE-m”
    b=”$(cat “$g/rebase-merge/head-name”)”
    elif [ -f “$g/MERGE_HEAD” ]
    then
    r=”|MERGING”
    b=”$(git symbolic-ref HEAD 2>/dev/null)”
    else
    if [ -f “$g/BISECT_LOG” ]
    then
    r=”|BISECTING”
    fi
    if ! b=”$(git symbolic-ref HEAD 2>/dev/null)”
    then
    if ! b=”$(git describe –exact-match HEAD 2>/dev/null)”
    then
    b=”$(cut -c1-7 “$g/HEAD”)…”
    fi
    fi
    fi

    if [ -n “$1” ]; then
    printf “$1” “${b##refs/heads/}$r”
    else
    printf ” (%s)” “${b##refs/heads/}$r”
    fi
    fi
    }

Leave a comment