Bash Prompt Snobbery
It's useful to customise your command-line prompt to show information about the current directory's Git repository. This can be as simple or complex as you want, but there are generally a few key pieces of information that most people want, like the current branch and the status of the working directory. Let's take a look at how to get started.
TL;DR
Put the following in your bash configuration e.g. ~/.bashrc
:
GIT_PS1_DESCRIBE_STYLE="describe"
GIT_PS1_SHOWCOLORHINTS="y"
GIT_PS1_SHOWDIRTYSTATE="y"
GIT_PS1_SHOWSTASHSTATE="y"
GIT_PS1_SHOWUNTRACKEDFILES="y"
GIT_PS1_SHOWUPSTREAM="verbose name git"
PROMPT_COMMAND='__git_ps1 "\u@\h:\w" " \$ "'
Now when you’re inside a git-controlled project your prompt will show git information:
The Command Prompt
There are a number of bash environment variables that relate to the command prompt ("PS" stands for "Prompt Statement"):
variable | description |
---|---|
PS0 | The value of this variable is expanded and displayed by interactive shells after reading a command and before the command is executed. |
PS1 | The value of this variable is expanded and used as the primary prompt string (this is generally the prompt you see when you open your terminal). The default is $ , unless you are the superuser, in which case it is # . |
PS2 | The value of this variable is expanded and used as the secondary prompt string. The default is > . |
PS3 | The value of this variable is used as the prompt for the select command. |
PS4 | The value of this variable is expanded and the value is printed before each command bash displays during an execution trace (set -x ). The first character is replicated multiple times, as necessary, to indicate multiple levels of indirection. The default is + . |
PROMPT_COMMAND | If set, the value is executed as a command prior to issuing each primary prompt. |
PROMPT_DIRTRIM | If set to a number greater than zero, the value is used as the number of trailing directory components to retain when expanding the \w and \W prompt string escapes. Characters removed are replaced with an ellipsis. |
Primary Prompt (PS1)
The primary prompt is the main variable we're interested in because it controls the prompt you see when you open your terminal. It can be modified directly in your terminal, but remember that to make a change permanent you'll need to set the variable in your ~/.bashrc
file and restart your terminal.
To change PS1 to the current working directory (\w
) followed by a dollar symbol:
$ PS1='\w \$ '
Newlines can used to create multi-line prompts:
$ PS1='\w\n\$ '
Bash allows prompt strings to be customized by inserting backslash-escaped special characters that are decoded. See backslash-escaped special characters for a complete list of all of special backslash-escaped characters.
if-else statements
If-else statements can be used. A good example is to indicate the exit status of the most recently executed command (red to indicate an error).
The following prints "ERROR" when a recently executed command fails:
$ PS1='\w $(if test $? = 0;then echo "\$";else echo "ERROR \$";fi) '
Instead of printing "ERROR" let's use color codes to show a prompt in red.
Color codes are surrounded with escape sequences (\[
/ \]
). Using \[
and \]
around color codes is necessary to prevent issues with command line editing, browsing, and completion.
$ PS1='\w $(if test $? = 0;then echo "\$";else echo "\[\e[31m\]\$\[\e[0m\]";fi) '
The Git Prompt
Git provides a shell function out-of-the-box for generating repository status. It's a plain ol' shell function, and available when you install Git. For example, cd into a git controlled project and run:
$ echo "$(__git_ps1)"
(master)
The __git_ps1
function accepts one argument. The argument is the format string. When no arguments are given the format string defaults to (%s)
. Git will automatically replace %s
with the repository status information:
$ echo "$(__git_ps1)"
(master)
$ echo "$(__git_ps1 "x %s y")"
x master y
The function can be used directly as command-substitution in PS1
:
$ PS1='\u@\h:\w$(__git_ps1) \$ '
Using PROMPT_COMMAND for a slightly faster prompt
For a slightly faster prompt use the PROMPT_COMMAND
variable. When the git prompt function is used with PROMPT_COMMAND
, it accepts three arguments: pre, post, and format. The format defaults to (%s)
:
$ PROMPT_COMMAND="__git_ps1 'x' ' y '"
x (master) y
$ PROMPT_COMMAND="__git_ps1 'x' ' y ' ' a %s b'"
x a (master) b y
And you can use if-else statements and color codes:
$ PROMPT_COMMAND='__git_ps1 "\u@\h:\w" " $(if test $? = 0;then echo "\$";else echo "\[\e[31m\]\$\[\e[0m\]";fi) "'
A complete example
GIT_PS1_DESCRIBE_STYLE="contains"
GIT_PS1_SHOWCOLORHINTS="y"
GIT_PS1_SHOWDIRTYSTATE="y"
GIT_PS1_SHOWSTASHSTATE="y"
GIT_PS1_SHOWUNTRACKEDFILES="y"
GIT_PS1_SHOWUPSTREAM="verbose name git"
PROMPT_COMMAND='__git_ps1 "\u@\h:\w" " $(if test $? = 0;then echo "\$";else echo "\[\e[31m\]\$\[\e[0m\]";fi) "'
My own prompt
I'm a big fan of multi-line prompts. It's not for everybody but I like the space it offers:
GIT_PS1_DESCRIBE_STYLE="describe"
GIT_PS1_SHOWCOLORHINTS="y"
GIT_PS1_SHOWDIRTYSTATE="y"
GIT_PS1_SHOWSTASHSTATE="y"
GIT_PS1_SHOWUNTRACKEDFILES="y"
GIT_PS1_SHOWUPSTREAM="verbose name git"
PROMPT_COMMAND='__git_ps1 "╭─ \w" "\n╰$(if test $? = 0;then echo "\$";else echo "\[\e[31m\]\$\[\e[0m\]";fi) " " ⎇ %s"'