Skip to content

Instantly share code, notes, and snippets.

@sbilstein
Last active December 31, 2015 11:59
Show Gist options
  • Save sbilstein/7983019 to your computer and use it in GitHub Desktop.
Save sbilstein/7983019 to your computer and use it in GitHub Desktop.
BASH prompt with git branch name and status. Fixed to handle directory names with spaces and checks to see if nested directories are under source control.
#!/bin/bash
# BASH prompt builder
#
# This is a script I use to generate BASH prompts that look like this:
# (master)*
# [sbilstei@sbilstei-mn1:~/localcode/git-sandbox]:$
#
# Basically user, the machine's hostname, current working directory tilde condensed and an optional branch name
# when navigating a git repo. The asterisk is visible if there are uncommitted changes.
#
# To use this script add the following lines to your .bash_profile:
#
# function prompt_command {
# export PS1=$(<scriptlocation>)
# }
# export PROMPT_COMMAND=prompt_command
#
# where <scriptlocation> is the location of this script. You will also need to set execute permissions on the script by typing:
# chmod 744 <script>
# By tying the execution of this script to PROMPT_COMMAND
# we can guarantee that the branch status gets updated on every new prompt. Check out this SO post on the
# topic: http://stackoverflow.com/a/11107564/608801
#
function git_changed {
if [ ! -z "$(git diff-index --name-only HEAD --)" ]; then
echo "*"
fi
}
# Substitute a leading path that's in $HOME for "~"
function pwd_short {
local dir="$PWD"
if [[ "$HOME" == ${dir:0:${#HOME}} ]] ; then
dir="~${dir:${#HOME}}"
fi
echo "${dir}"
}
function git_branch_and_status {
local maxlen=30
local truncatelen=maxlen-3
local is_repo=$(git rev-parse --is-inside-work-tree 2> /dev/null)
if [ "$is_repo" = "true" ]; then
ref=$(git symbolic-ref HEAD 2> /dev/null)
local branch=${ref#refs/heads/}
namelength=${#branch}
if [ $namelength -gt $maxlen ]; then
branch="${branch:0:${truncatelen}}..."
else
branch="${branch}"
fi
echo "(${branch})$(git_changed)\n"
else
echo ""
fi
}
echo -e "$(git_branch_and_status)[$USER@$HOSTNAME:$(pwd_short)]$ "
@simsaens
Copy link

You might want to wrap "$(git diff-index --name-only HEAD --)" in double quotes, otherwise this script does not handle working directories containing spaces.

@joeyyang
Copy link

I got this to work by saving this as an (extensionless) file in my ~/bin directory ("bash_prompt"), then by placing the below code in my /.bash_profile, replacing "< scriptlocation >" below with "/bin/bash_prompt

function prompt_command {
   export PS1=$(<scriptlocation>)
 }
 export PROMPT_COMMAND=prompt_command 

@kevinkyyro
Copy link

My prompt would be achieved by increasing maxlen (my branch and pwd are on their own line so I don't bother truncating them) and changing the last line to:

echo -e "\n(\w)-[$(git_branch_and_status)]\n\u@\h-[\D{%H:%M}]$ "

The effect is:

                                          # intentional newline        
(~/path/to/repo)-[JIRA-42-branch-name]    # pwd and branch
user@host-[12:40]$                        # prompt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment