asemanfar - a blog about programming

Current Git Branch in Bash Prompt

April 12, 2008

Earlier today, my roommate and I were enjoying our afternoon watching the TextMate for Rails 2 Peepcode and I noticed that in the bash prompt, the current branch was shown in parenthesis. I thought this was a wonderful idea and thought I'd add it to my own bash prompt.

Update: Some much better alternative methods have been posted in the comments, please take a look below.

Here is the code to do it:

   1  export PS1="\[\033[38m\]\u@\h\[\033[01;34m\] \w \[\033[31m\]\`ruby -e \"print (%x{git branch 2> /dev/null}.grep(/^\*/).first || '').gsub(/^\* (.+)$/, '(\1) ')\"\`\[\033[37m\]$\[\033[00m\] "

This will make your bash prompt look like this:

   1  user@hostname currentDirectory (branch name) $

The important part of the PS1 in the first code snippet is this:

   1  # this goes somewhere in your PS1 (it'll make the branch name red)
   2  \[\033[31m\]\`ruby -e \"print (%x{git branch 2> /dev/null}.grep(/^\*/).first || '').gsub(/^\* (.+)$/, '(\1) ')\"\`\[\033[37m\]

I decided to try to do this with sed and not ruby. I came up with this:

   1  export PS1="...\`git branch 2> /dev/null | grep -e ^* | sed -E  s/^\\\\\\\\\*\ \(.+\)$/\(\\\\\\\\\1\)\ /\`\[\033[37m\]$\[\033[00m\] "
   2  # no, your browser is not having rendering issues
   3  # there seriously are that many backslashes

Other than the disgusting backslashes, it's pretty nice. If you use single quotes on the outside instead of double, you can lose a few backslashes:

   1  export PS1='...`git branch 2> /dev/null | grep -e ^* | sed -E  s/^\\\\\*\ \(.+\)$/\(\\\\\1\)\ /`\[\033[37m\]$\[\033[00m\] '

Comments

posted by Evgeny on 04/14/08 01:19 AM PDT

Mine:

   1  PS1='\[\033[00;32m\]\u\[\033[01m\]@\[\033[00;36m\]\h\[\033[01m\]:\[\033[00;35m\]\w\[\033[00m\]\[\033[01;30m\](`git branch 2>/dev/null|tr -d \*\ `)\[\033[00m\]\$ '
posted by Arya Asemanfar on 04/14/08 01:36 AM PDT

Evgeny,

Your solution doesn't work quite the same way. git branch outputs every local branch, so your solution would list all the branches, not just the current one.

So to fix that, you can pipe git branch through grep:

   1  git branch 2>/dev/null|grep -e ^* | tr -d \*\

Also, your solution includes the parenthesis regardless if you're in a git directory or not.

I'm sure there is a better way to do what I'm doing using sed or awk, but I'm not well-versed in either so I stuck to ruby.

Update: I took a stab at it in sed. (see bottom of post)

posted by adam on 04/14/08 02:50 AM PDT

There is already a function to do this in the git distribution. If you check out the source there is a directory called contrib which has a bash completion file that gives you a __git_ps1 function.

Then you can just put \$(__git_ps1) somewhere in your PS1 and get the current branch. It doesn't output anything when you're not in a git directory. It also gives you branch name and subcommand tab completion.

posted by Philip Hofstetter on 04/14/08 04:03 AM PDT

this ends up in my ZSH prompt, but it should work for bash too and comes with as few backslashes as possible, which makes it even readabel:

   1  git_branch=`git branch 2>/dev/null | grep -e '^*' | sed -E 's/^\* (.+)$/(\1) /'`
   2    PS1="... $git_branch$path_prompt ..."

Philip

posted by Philip Hofstetter on 04/14/08 04:35 AM PDT

I've adapted the solution to work without any backslashes in a ZSH prompt theme environment.

Here's my take on this:

http://www.gnegg.ch/2008/04/git-branch-in-zsh-prompt/

Philip

posted by Timothy Johnson on 04/14/08 05:04 AM PDT

Here is mine

   1  parse_git_branch() {
   2    git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(\1)/'
   3  }
   4  PS1="\w\$(parse_git_branch) $ "
posted by Rodrigo Urubatan on 04/14/08 05:47 AM PDT

I used a cut because the original solution was inclusing all branches upto the one I was working on, and one line break for each too ... the "cut version" is:

   1  git branch 2>/dev/null|cut -f2 -d\* -s
posted by Nathan Weizenbaum on 04/14/08 07:48 AM PDT

I've been doing the same thing, but I've found that

   1  git name-rev

tends to give more detailed output when you aren't on a branch (e.g. try checking out master^). The code I use is:

   1  git name-rev HEAD 2> /dev/null | awk "{ print \\$2 }"

I actually nabbed that code from someone else's bashrc a while ago, but I forgot to save a link and so can't give credit, unfortunately.

posted by Eric Goodwin on 04/14/08 10:51 AM PDT

If you use the auto completion script that come with Git, you get the auto complete functionality plus the __git_ps1 method that Adam mentioned above. You can place the __git_ps1 method in your PS1 and get the branch name in your prompt. I've got a short tutorial on getting it working on OS X at http://blog.ericgoodwin.com/2008/4/10/auto-completion-with-git.

Eric

posted by Jeremy Friesen on 04/14/08 05:41 PM PDT

Well that was somewhat botched. Here it goes In ~/.bashrc

   1  parse_git_branch() {
   2    git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/(git::\1)/'
   3  }
   4  parse_svn_branch() {
   5    parse_svn_url | sed -e 's#^'"$(parse_svn_repository_root)"'##g' | awk -F / '{print "(svn::"$1 "/" $2 ")"}'
   6  }
   7  parse_svn_url() {
   8    svn info 2>/dev/null | grep -e '^URL*' | sed -e 's#^URL: *\(.*\)#\1#g '
   9  }
  10  parse_svn_repository_root() {
  11    svn info 2>/dev/null | grep -e '^Repository Root:*' | sed -e 's#^Repository Root: *\(.*\)#\1\/#g '
  12  }
  13  export PS1="\[\033[00m\]\u@\h\[\033[01;34m\] \w \[\033[31m\]\$(parse_git_branch)\$(parse_svn_branch) \[\033[00m\]$\[\033[00m\] "

For git directories

   1  jeremyf@jnf ~/ccs_portal (git::master) $

For svn directories

   1  jeremyf@jnf ~/ccs_main/app/controllers (svn::ccs_main/trunk) $
posted by Geoffrey Grosenbach on 04/15/08 07:49 PM PDT

Thanks for the plug!

I first learned it here:

http://acts.as.streeteasy.com/archives/2007/12/19/git_in_your_prompt/

posted by Rob Olson on 04/18/08 03:40 PM PDT

After reading this post I switched over to the __git_ps1 method.

   1  export PS1='\[\033[01;32m\]\h\[\033[01;34m\] \w\[\033[31m\]$(__git_ps1 "(%s)") \[\033[01;34m\]$\[\033[00m\] '

The relevant part being...

   1  $(__git_ps1 "(%s)")
posted by Eddy Petrisor on 08/21/08 06:18 AM PDT

the 'grep | sed' part can be avoided and implemented in a single sed:

   1  parse_git_branch ()
   2  {
   3  	git name-rev HEAD 2> /dev/null | sed 's#HEAD\ \(.*\)#(git::\1)#'
   4  }
   5  parse_svn_branch() {
   6  	parse_svn_url | sed -e 's#^'"$(parse_svn_repository_root)"'##g' | awk -F / '{print "(svn::"$1 "/" $2 ")"}'
   7  }
   8  parse_svn_url() {
   9  	svn info 2>/dev/null | sed -ne 's#^URL: ##p'
  10  }
  11  parse_svn_repository_root() {
  12  	svn info 2>/dev/null | sed -ne 's#^Repository Root: ##p'
  13  }
posted by Geoffrey Grosenbach on 11/26/08 08:56 PM PST

I've since added a Unicode skull and crossbones when I'm in a branch with uncommitted changes:

http://www.scrnshots.com/users/topfunky/screenshots/89842


Leave a Comment