PS1 line with Git current branch and colors
Asked Answered
G

16

80

Here is my current PS1:

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

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

Gnat answered 9/11, 2010 at 13:1 Comment(0)
P
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.

Pachydermatous answered 9/11, 2010 at 20:7 Comment(4)
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: askubuntu.com/questions/24358/…Streptokinase
This is a really good source for bash prompt coloring as wellBruyn
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 mywiki.wooledge.org/BashFAQ/037 . And use the suggested \[ and \] if assigning to PS1: mywiki.wooledge.org/BashFAQ/053Skutchan
Just like @Streptokinase 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\] $ 'Gonion
K
150

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.

Kephart answered 22/5, 2011 at 9:5 Comment(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 \*)`'Quarters
git rev-parse --abbrev-ref HEADLunalunacy
P
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.

Pachydermatous answered 9/11, 2010 at 20:7 Comment(4)
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: askubuntu.com/questions/24358/…Streptokinase
This is a really good source for bash prompt coloring as wellBruyn
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 mywiki.wooledge.org/BashFAQ/037 . And use the suggested \[ and \] if assigning to PS1: mywiki.wooledge.org/BashFAQ/053Skutchan
Just like @Streptokinase 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\] $ 'Gonion
M
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

Mainis answered 9/11, 2010 at 20:56 Comment(0)
A
19
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

Ammons answered 4/5, 2012 at 23:22 Comment(2)
This does only show the git branch in the root folder of the git repositoryMarguritemargy
since git worktrees are a thing and result in .git being a file a [ -r .git ] might be an improvement for some.Euonymus
A
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.

Alisonalissa answered 15/8, 2012 at 19:25 Comment(5)
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.Ritchey
@darKoram: You probably need to escape a $ with a ` \ `.Douceur
Awesome, Ill hack it around but taht was more or less, what i was looking for! +1 from me:)Ventricle
These days I'd just recommend powerline. There are (at least) python, go and rust versions.Alisonalissa
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!Anthropography
M
11

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'
Margie answered 21/6, 2015 at 9:55 Comment(9)
Nice one, +1. I am still looking for one which would display the current user.name.Inadvisable
Try adding this somewhere in your prompt: $(git config --global --get user.name)Margie
If you want the /current/ user.name, why would you pull from the --global config?Antilogism
Would you please provide a screenshot?Lunalunacy
@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.Margie
Please note that this way of using fancyx will destroy your multiline prompt (same as when not escaping colors correctly unix.stackexchange.com/questions/105958/…). 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 \[\]Seine
@Inadvisable Take a look at my answer above, it includes the username.Hoelscher
@Inadvisable To be fair I posted that about three years ago! ;)Hoelscher
@DanL And you waited all that time to tell me? Sorry I missed it at the time!Inadvisable
F
5
  1. Add 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

Feel answered 24/10, 2019 at 10:2 Comment(1)
This is broken because of the double quotes. See e.g. @ryanpcmcquen's answer for a fixed version.Immuno
H
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 .../).

Hoelscher answered 9/2, 2016 at 1:45 Comment(0)
E
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.

Emmerie answered 7/3, 2014 at 11:41 Comment(0)
E
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://mcmap.net/q/13235/-ps1-line-with-git-current-branch-and-colors
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.

Educatee answered 9/11, 2018 at 15:55 Comment(0)
T
2

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

Tactical answered 9/11, 2010 at 13:2 Comment(2)
I think I'm not escaping the tput call correctly. Could you give an example please?Gnat
@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.Biquadrate
O
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\$ "
Overthecounter answered 20/3, 2014 at 15:37 Comment(1)
can you explain the components ?Izabel
Q
0

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

Quadrivalent answered 14/11, 2010 at 0:57 Comment(0)
C
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

Colyer answered 13/9, 2021 at 8:32 Comment(0)
E
0

Here is how I did this:

eyes=(O o ∘ ◦ ⍤ ⍥)
en=${#eyes[@]}
mouth='_'
linesymbol='-'

RED='\e[31m'
GRN='\e[32m'
YLW='\e[33m'
BLU='\e[34m'
MGN='\e[35m'
DEF='\e[0m'
BLD='\e[1m'
DIM='\e[2m'

face () { # gen random face
    [[ $error -gt 0 ]] && ecolor=$RED || ecolor=$YLW
    [[ $1 ]] && printf "${eyes[$[RANDOM%en]]}$mouth${eyes[$[RANDOM%en]]}" \
             || printf "$ecolor${eyes[$[RANDOM%en]]}$YLW$mouth$ecolor${eyes[$[RANDOM%en]]}$DEF"
}

info () { error=$? git_tst= git_clr=
    [[ -d .git ]] && {
         git_tst=($(git -c color.ui=never  status -sb)) git_tst="GIT ${git_tst[*]} " # Test output
         git_clr=($(git -c color.ui=always status -sb)) git_clr="GIT ${git_clr[*]} " # Colored output
    }
    [[ $debian_chroot ]] && chrt="($debian_chroot)" || chrt=  # If in chroot
    name_length="{ $HOSTNAME$chrt }"
    name_length=${#name_length}
    face_tst='O_o  o_O'
    top_line_left=$[(COLUMNS-name_length)/2]
    top_line_right=$[COLUMNS-(top_line_left+name_length)]
    printf -v top_line "%${top_line_left}s{_S_$DEF$BLD$HOSTNAME$chrt${DEF}_S_$GRN}%${top_line_right}s"
    printf -v bot_line "%${COLUMNS}s"
    printf -v date  "%(%a %d %b %T)T"
    top_line=${top_line// /-}
    top_line=$GRN${top_line//_S_/ }$DEF
    bot_line=$GRN${bot_line// /-}$DEF
    spaces=$[COLUMNS-${#date}-${#PWD}-${#git_tst}-${#face_tst}]; ((spaces<0)) && spaces=1
    printf "$top_line\n$(face) $BLD$BLU$PWD$DEF%${spaces}s$git_clr$DIM$date $(face)\n$bot_line"
}


PS1='\n$(info)\n$ '
case "$TERM" in xterm*|rxvt*) PS1="\[\e]0;$(face 1) \h\w\a\]$PS1";; esac

This code is supposed to go to ~/.bashrc. The result looks like this:

info bar

Code is available here

Else answered 13/9, 2021 at 12:55 Comment(0)
S
-1

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\$ "
Sven answered 31/1, 2014 at 15:58 Comment(1)
-1 for hardcoded path to the repository. This would work for one repository only, so its usability is in theory only.Protectionism

© 2022 - 2024 — McMap. All rights reserved.