76

Here is my current PS1:

export PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '

How can I display the current branch in a different color?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
cfischer
  • 24,452
  • 37
  • 131
  • 214

16 Answers16

147

Here is, part by part (and no Ruby):

function color_my_prompt {
    local __user_and_host="\[\033[01;32m\]\u@\h"
    local __cur_location="\[\033[01;34m\]\w"
    local __git_branch_color="\[\033[31m\]"
    #local __git_branch="\`ruby -e \"print (%x{git branch 2> /dev/null}.grep(/^\*/).first || '').gsub(/^\* (.+)$/, '(\1) ')\"\`"
    local __git_branch='`git branch 2> /dev/null | grep -e ^* | sed -E  s/^\\\\\*\ \(.+\)$/\(\\\\\1\)\ /`'
    local __prompt_tail="\[\033[35m\]$"
    local __last_color="\[\033[00m\]"
    export PS1="$__user_and_host $__cur_location $__git_branch_color$__git_branch$__prompt_tail$__last_color "
}
color_my_prompt

Looks like this (with my own terminal palette):

Colored prompt

Also, see this and this article.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
shaman.sir
  • 3,198
  • 3
  • 28
  • 36
  • 2
    @AhmedFasih - I've added a dirty state variable to mine: ``local __git_dirty='`git rev-parse 2>/dev/null && (git diff --no-ext-diff --quiet --exit-code 2> /dev/null || echo -e \*)`'`` – Unglued May 29 '15 at 19:54
  • 1
    `git rev-parse --abbrev-ref HEAD` – mikezter May 13 '17 at 21:03
39

You can wrap the part that you want in colour with the following:

\e[0;32m - sets colour (in this case, to green)

\e[m - sets colour back to the default

For example, this sets the prompt to the last token of the current path, in green, followed by $ in the default colour:

export PS1='\e[0;32m\w\e[m $'

Other colours are available too. Have a look at this article under colorization for a comprehensive list of alternatives.

bzeaman
  • 1,128
  • 11
  • 28
Simon Whitaker
  • 20,506
  • 4
  • 62
  • 79
  • 36
    It should be noted that it is best to wrap the colour codes between `\[` and `\]`, otherwise you could end up having problems with a long command line not wrapping correctly because bash counts the wrong number of characters: http://askubuntu.com/questions/24358/how-do-i-get-long-command-lines-to-wrap-to-the-next-line – Kjir Oct 08 '13 at 16:20
  • [This](https://misc.flogisoft.com/bash/tip_colors_and_formatting) is a really good source for bash prompt coloring as well – Steve Whitmore Oct 03 '19 at 16:21
  • Also I *strongly* encourage **not** to hardcode color codes. Use `$(tput setaf 2)` (2 for green, 1 for red, 3 for yellow, etc), `$(tput bold)` for bold and `$(tput sgr0)` to reset. See https://mywiki.wooledge.org/BashFAQ/037 . And use the suggested `\[` and `\]` if assigning to `PS1`: https://mywiki.wooledge.org/BashFAQ/053 – MestreLion Aug 17 '20 at 02:15
  • 2
    Just like @Kjir said, to avoid having problems with a long command line not wrapping correctly, the most correct is: `export PS1='\[\e[0;32m\]\w\[\e[0m\] $ '` – MhagnumDw Dec 16 '20 at 21:32
27

Here is my PS1 line:

\n\[\e[1;37m\]|-- \[\e[1;32m\]\u\[\e[0;39m\]@\[\e[1;36m\]\h\[\e[0;39m\]:\[\e[1;33m\]\w\[\e[0;39m\]\[\e[1;35m\]$(__git_ps1 " (%s)")\[\e[0;39m\] \[\e[1;37m\]--|\[\e[0;39m\]\n$

alt text

cmcginty
  • 113,384
  • 42
  • 163
  • 163
18
function pc {
  [ -d .git ] && git name-rev --name-only @
}
PS1='\e];\s\a\n\e[33m\w \e[36m$(pc)\e[m\n$ '

ps1

Source

Zombo
  • 1
  • 62
  • 391
  • 407
  • 1
    This does only show the git branch in the root folder of the git repository – anstue Jun 06 '19 at 10:08
  • since git worktrees are a thing and result in `.git` being a file a `[ -r .git ]` might be an improvement for some. – danblack Aug 11 '20 at 06:17
13

This is my PS1 solution.

It looks great on a Mac with the Novel theme. Sorry, but my indentation got munged a bit. Hack it till you like it.

function we_are_in_git_work_tree {
    git rev-parse --is-inside-work-tree &> /dev/null
}

function parse_git_branch {
    if we_are_in_git_work_tree
    then
    local BR=$(git rev-parse --symbolic-full-name --abbrev-ref HEAD 2> /dev/null)
    if [ "$BR" == HEAD ]
    then
        local NM=$(git name-rev --name-only HEAD 2> /dev/null)
        if [ "$NM" != undefined ]
        then echo -n "@$NM"
        else git rev-parse --short HEAD 2> /dev/null
        fi
    else
        echo -n $BR
       fi
    fi
}

function parse_git_status {
    if we_are_in_git_work_tree
    then
    local ST=$(git status --short 2> /dev/null)
    if [ -n "$ST" ]
    then echo -n " + "
    else echo -n " - "
    fi
    fi
}

function pwd_depth_limit_2 {
    if [ "$PWD" = "$HOME" ]
    then echo -n "~"
    else pwd | sed -e "s|.*/\(.*/.*\)|\1|"
    fi
}

COLBROWN="\[\033[1;33m\]"
COLRED="\[\033[1;31m\]"
COLCLEAR="\[\033[0m\]"

# Export all these for subshells
export -f parse_git_branch parse_git_status we_are_in_git_work_tree pwd_depth_limit_2
export PS1="$COLRED<$COLBROWN \$(pwd_depth_limit_2)$COLRED\$(parse_git_status)$COLBROWN\$(parse_git_branch) $COLRED>$COLCLEAR "
export TERM="xterm-color"

If you are checked out at a branch, you get the branch name.

If you are in a just init'd Git project, you just get '@'.

If you are headless, you get a nice human name relative to some branch or tag, with an '@' preceding the name.

If you are headless and not an ancestor of some branch or tag you just get the short SHA1.

In addition, a red '-' signifies a clean work directory and index, and a red '+' signifies the opposite.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
polypus74
  • 429
  • 4
  • 8
  • This is nice, but for me on a mac it doesn't update when I switch branches. Having difficulties getting it to delay evaluation. +1 for readability. – darKoram Oct 27 '13 at 05:43
  • @darKoram: You probably need to escape a `$` with a ` \ `. – Gauthier Feb 03 '15 at 09:36
  • Awesome, Ill hack it around but taht was more or less, what i was looking for! +1 from me:) – Svetlin Tonchev Jan 04 '18 at 15:15
  • 1
    These days I'd just recommend powerline. There are (at least) python, go and rust versions. – polypus74 Jan 13 '19 at 16:51
  • On your recommendation, I got Powerline (`python3 -m pip install powerline-status`) up and running in iTerm2 in a short amount of time. I think I like it! – harperville Dec 22 '22 at 20:17
10

My uber-powerful multi-line Linux prompt!

Put it either in your .bashrc or better: save it in /etc/bash-prompt and source it from your .bashrc.
Using tput is supposed to be the right way to do colors.

#!/bin/bash

set_prompt()
{
   local last_cmd=$?
   local txtreset='$(tput sgr0)'
   local txtbold='$(tput bold)'
   local txtblack='$(tput setaf 0)'
   local txtred='$(tput setaf 1)'
   local txtgreen='$(tput setaf 2)'
   local txtyellow='$(tput setaf 3)'
   local txtblue='$(tput setaf 4)'
   local txtpurple='$(tput setaf 5)'
   local txtcyan='$(tput setaf 6)'
   local txtwhite='$(tput setaf 7)'
   # unicode "✗"
   local fancyx='\342\234\227'
   # unicode "✓"
   local checkmark='\342\234\223'
   # Line 1: Full date + full time (24h)
   # Line 2: current path
   PS1="\[$txtbold\]\[$txtwhite\]\n\D{%A %d %B %Y %H:%M:%S}\n\[$txtgreen\]\w\n"
   # User color: red for root, yellow for others
   if [[ $EUID == 0 ]]; then
       PS1+="\[$txtred\]"
   else
       PS1+="\[$txtyellow\]"   
   fi
   # Line 3: user@host
   PS1+="\u\[$txtwhite\]@\h\n"
   # Line 4: a red "✗" or a green "✓" and the error number
   if [[ $last_cmd == 0 ]]; then
      PS1+="\[$txtgreen\]$checkmark \[$txtwhite\](0)"
   else
      PS1+="\[$txtred\]$fancyx \[$txtwhite\]($last_cmd)"
   fi
   # Line 4: green git branch
   PS1+="\[$txtgreen\]$(__git_ps1 ' (%s)')\[$txtwhite\]"
   # Line 4: good old prompt, $ for user, # for root
   PS1+=" \\$ "
}
PROMPT_COMMAND='set_prompt'
cylgalad
  • 109
  • 1
  • 2
  • 5
  • Nice one, +1. I am still looking for one which would display the current user.name. – VonC Jun 21 '15 at 10:18
  • Try adding this somewhere in your prompt: $(git config --global --get user.name) – cylgalad Jun 21 '15 at 17:10
  • If you want the /current/ user.name, why would you pull from the --global config? – Gordon Jul 31 '15 at 18:48
  • 4
    Would you please provide a screenshot? – mikezter May 13 '17 at 21:05
  • 1
    @YuriGhensev: you need to source git-prompt.sh. For my distro (Archlinux) its location is: /usr/share/git/completion/git-prompt.sh, on other distros it's somewhere else (it can even have another filename) and you might have to install some extra git package. – cylgalad Nov 29 '17 at 08:58
  • Please note that this way of using `fancyx` will destroy your multiline prompt (same as when not escaping colors correctly https://unix.stackexchange.com/questions/105958/terminal-prompt-not-wrapping-correctly). Looks like bash in not really good in understanding characters wide. So simple workaround will be to enclose 2 of 3 parts of those wide symbold into `\[\]` – The Godfather Sep 14 '18 at 08:55
  • @VonC Take a look at my answer above, it includes the username. – Dan L Feb 26 '19 at 00:52
  • @VonC To be fair I posted that about three years ago! ;) – Dan L Feb 26 '19 at 07:13
  • 1
    @DanL And you waited all that time to tell me? Sorry I missed it at the time! – VonC Feb 26 '19 at 07:15
4

For my Mac with the Homebrew theme, this works really well. Fully debugged and very fast, and completely self-contained. BONUS: Smart enough to ONLY show a git branch as part of the prompt when you're actually in a git repo! :)

# Color prompt for git
reset=$(tput sgr0)
boldgreen=$(tput setaf 2)$(tput bold)
cyan=$(tput sgr0)$(tput setaf 6)
boldred=$(tput setaf 1)$(tput bold)
boldwhite=$(tput setaf 7)$(tput bold)
boldyellow=$(tput setaf 3)$(tput bold)

PARENCLR=$'\001\e[0;36m\002'
BRANCHCLR=$'\001\e[1;33m\002'

alias branchname="git branch 2>/dev/null | sed -ne 's/^* \(.*\)/ ${PARENCLR}(${BRANCHCLR}\1${PARENCLR}\)/p'"

GIT_STATUS='$(branchname)'

PROMPT_CHAR="\$"
PS1="\[$boldgreen\]\u\[$cyan\]::\[$boldred\]\h \[$cyan\]{\[$boldwhite\].../\W\[$cyan\]}\[$reset\]$GIT_STATUS\[$reset\]$PROMPT_CHAR "

Here's what it looks like: Mac + Homebrew + Color Git Prompt

If you want to have the full path (or remove the .../), then just change the -W to -w (and remove the .../).

Dan L
  • 325
  • 1
  • 6
4

Quick hack:

  1. Adding this to ~/.bashrc:
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\]$ "
  1. Restart the terminal, or source ~/.bashrc:

enter image description here

More detail: https://medium.com/@thucnc/how-to-show-current-git-branch-with-colors-in-bash-prompt-380d05a24745

thucnguyen
  • 1,706
  • 15
  • 14
3

Take a look at liquidprompt:

https://github.com/nojhan/liquidprompt

Maybe a bit too heavy for your requirements, but you can switch features off by setting

LP_ENABLE_...=0

See the documentation on above page.

botkop
  • 934
  • 1
  • 8
  • 17
3

Modified version of @cmcginty's prompt that adds in the git parsing function and uses slightly different spacing:

# So I know where I am in repos:
parse_git_branch() {
    git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}

# Modified from:
# https://stackoverflow.com/a/4138531/2662028
export PS1='\n\[\e[1;37m\]|-- \[\e[1;32m\]\u\[\e[0;39m\]@\[\e[1;36m\]\h\[\e[0;39m\]:\[\e[1;33m\]\w\[\e[0;39m\]\[\e[1;35m\]$(parse_git_branch " (%s)")\[\e[0;39m\] \[\e[1;37m\]--|\[\e[0;39m\]\n\$ '

This also uses \$ in the prompt instead of $, which means you will get # when you are root.

ryanpcmcquen
  • 6,285
  • 3
  • 24
  • 37
2

Just invoke tput with the appropriate parameters. See the tput(1) and terminfo(5) man pages.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • I think I'm not escaping the tput call correctly. Could you give an example please? – cfischer Nov 09 '10 at 13:18
  • 4
    @Fernando: Be sure to wrap your `tput` command in `\[` and `\]` so the characters it outputs are not counted in the length of the prompt. This will keep the prompt from getting messed up when you scroll through history, for example. – Dennis Williamson Nov 09 '10 at 16:18
1

Here's mine

export PS1="\n\[\033[1;30m\][$$:$PPID - \j:\!\[\033[1;30m\]]\[\033[0;36m\] \T \
\[\033[1;30m\][\[\033[1;34m\]\u@\H\[\033[1;30m\]:\[\033[0;37m\]${SSH_TTY:-o} \
\[\033[0;32m\]+${SHLVL}\[\033[1;30m\]] \[\033[1;37m\]\w\[\033[0;37m\]\[\033[1;34m\]\$(__git_ps1 \" (%s)\") \[\033[0;37m\] \n\$ "
Tony Lâmpada
  • 5,301
  • 6
  • 38
  • 50
0

Here is a Windows/Cygwin/Bash solution.

Add the following to your ~/.bashrc file.

xxx is the location of your local Git repository.

GetBranch()
{
    cat /cygdrive/c/xxx/.git/HEAD | sed 's+^ref: refs/heads/++'
}
export PS1="\[\e]0;\w\a\]\n\[\e[32m\]\u@\h \[\e[36m\]\$(GetBranch) \[\e[33m\]\w \[\e[0m\] \n\$ "
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ellis
  • 395
  • 3
  • 8
0

For more complicated status of Git you can use some larger script.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mpapis
  • 52,729
  • 14
  • 121
  • 158
0

This PS1 will color your current git branch in yellow:

export PS1="[\033[38;5;11m]\u[$(tput sgr0)]@\h:[$(tput sgr0)][\033[38;5;6m][\w][$(tput sgr0)][\033[38;5;226m]($(git branch 2>/dev/null | grep '^*' | colrm 1 2))[$(tput sgr0)]: [$(tput sgr0)]"

To see in a more interactive way the how the building of a PS1 string can be done (other ways are possible obviously), here the link to a very handy PS1 string generator for your .bashrc. I used it for the string above:

http://bashrcgenerator.com/

It solves in a simple way your question and more generally the issue of building of a customized and colorized shell prompt, including the current git branch

JRodrigoF
  • 855
  • 1
  • 11
  • 20
0

Take a look at this project info-bar

Ivan
  • 6,188
  • 1
  • 16
  • 23