I set up a PROMPT_COMMAND to display the current branch while I'm in a git repo.

The relevant part of my .bashrc is:

export PS1=" \[\033[34m\]\$\[\033[0m\] "
export PROMPT_COMMAND="$HOME/bin/myprompt"

where ~/bin/myprompt is:

#!/usr/bin/env ruby
green = "\033[32m"
bold = "\033[1m"
underline = "\033[4m"
reset = "\033[0m"

home_regex = Regexp.new "^#{ENV["HOME"]}"
Dir.chdir ENV["PWD"]

out = 
  underline + bold + green +
  `pwd`.gsub(home_regex, "~").chomp +

if `git log 2>&1 | grep ^fatal`.chomp == ""
  out += "#{underline}#{green} (#{`git branch | grep ^\* | sed s/^..//g`.chomp})#{reset}"

print out

It works fine for the most part, the only problem is that when I use the arrow keys to scroll through command history, sometimes the command gets written over my prompt. Suppose the following session:

~ $ pwd
~ $ cd sibilant
~/sibilant (master) $ pwd
~/sibilant (master) $

Then I press the up arrow to scroll through command history. each line shows the result of one press of the arrow:

~/sibilant (master) $ pwd
~/sibilant (master) $ cd sibilant

as you can see, the last time I pressed the arrow the command was written over my prompt.

Has anyone experienced this and/or know how to fix it?


2 Answers 2


Instead of putting it in PROMPT_COMMAND, put it in PS1:

PS1='$($HOME/bin/myprompt) \[\033[34m\]\$\[\033[0m\] '

When it's in PS1, bash counts the number of characters that get printed so that it can correctly redraw when you scroll through your history. That's why bash has the \[ and \] special characters—they tell bash that the enclosed characters are not printable, which helps bash figure out how to redraw the prompt when necessary.

Note that the command substitution is inside the single quotes. This prevents expansion at assignment time. If the command substitution was in double quotes or unquoted, the output of myprompt would be captured once at assignment time and remain static. In order to support variable values that change over time, the shell expands the value of PS1 each time the prompt is displayed. This means that expansion should be prevented at assignment time by quoting. It also means that you need to be careful about speed: if the command substitution takes 1 second to complete, then your prompt will take 1 second to display.

  • Thanks, but wouldn't that statically assign the output of myprompt to PS1? I remember trying to do something like that before.
    – adrusi
    Feb 13, 2012 at 3:22
  • 1
    Oops, that's a bug. I fixed it. The command substitution should be inside the single quotes. I'm in the habit of expanding variables and command substitutions at assignment time because that's what I want 99% of the time. PS1 is one of the rare exceptions. Feb 13, 2012 at 14:57
  • Thanks for the detailed explanation; this has helped me fix my PS1. I had PS1='\033]0;\u@\h\007[\[\033[01;32m\]\u@\h\[\033[00m\] \[\033[01;34m\]\w\[\033[00m\]]\$ ' which sets the window title and shows 'user@host full-path $' but the cursor was wrapping unexpectedly. After adding \[ and \] to look like this: PS1='\[\033]0;\u@\h\007\][\[\033[01;32m\]\u@\h\[\033[00m\] \[\033[01;34m\]\w\[\033[00m\]]\$ ' it works fine! Jun 30, 2014 at 10:52

PROMPT_COMMAND can contain a command that is executed before the new prompt is printed by bash (so before PS1 is evaluated).

With git 1.8.1, code to do this effectively with PROMPT_COMMAND was released. See using git-prompt.sh with PROMPT_COMMAND. The code can work with earlier versions of git, just copy the file contrib/completion/git-prompt.sh to a place where you can source it from your .bashrc.



You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .