I like to keep my bash prompt really minimal. I’m not into colours. I’m not into fancy fonts. I want my prompt to show contextual information so I can focus on the work I’m doing.
By default, macOS gives you this terminal:
I fucking hate it. Why do I need to see my machine name every time I open the terminal? Phooey.
Plus, when I navigate to a git repo, it doesn’t even show what branch I’m on. Double phooey.
My setup
Here’s what I have and I’m really happy with it.
What do I like about it?
Couple of things:
- Shows me what user I’m logged in as (good on unix systems when you want to switch between root and normal user)
- Shows me the full (read FULL) path of where I am. Yes, FULL.
- Shows me the branch I’m on (if I’m in a git repo)
Things I don’t need here:
- Machine name
- Date
- 10 billion colours
- Emoji. Well…
How to set it up
If you’re really impressed by it and just want the code, copy paste the following in your ~/.bash_profile
and move on with your life.
git_prompt() {
local branchName="";
# Check if the current directory is in a Git repository.
if git rev-parse --git-dir > /dev/null 2>&1; then
branchName="$(git symbolic-ref --quiet --short HEAD 2> /dev/null || \
git rev-parse --short HEAD 2> /dev/null || \
echo '(unknown)')";
echo -e "(${branchName})";
else
return;
fi;
}
PS1="\n[\u] at \w";
PS1+=" \$(git_prompt)";
PS1+="\n=> ";
If you’re like me and want to understand what this gibberish means, read on.
The git_prompt()
method spits out the current branch name, if it exists. Let’s try to break it down.
Step 1
Let’s run the first half of the command in a git repo and a normal folder and see what happens
[kunalnagar] at ~/Documents/Code/personal-main (updates-v3)
=> git rev-parse --git-dir
.git
[kunalnagar] at ~/Documents/Code/personal-main (updates-v3)
=> cd ..
[kunalnagar] at ~/Documents/Code
=> git rev-parse --git-dir
fatal: not a git repository (or any of the parent directories): .git
So basically, this command is used to check if our current working directory is a git repo or not.
What’s the writing to /dev/null
and 2>&1
mean? Read more here
Step 2
Once we’ve figured out that we are, actually, inside a git repo, we need to figure out what branch we’re in. Now please note that this can get fairly complicated with detached HEAD states etc. which is where most solutions on the internet fail. This is the best one I’ve found that works across a wide range of scenarios.
[kunalnagar] at ~/Documents/Code/personal-main (updates-v3)
=> git symbolic-ref --quiet --short HEAD 2> /dev/null
updates-v3
[kunalnagar] at ~/Documents/Code/personal-main (updates-v3)
=> cd ..
[kunalnagar] at ~/Documents/Code
=> git symbolic-ref --quiet --short HEAD 2> /dev/null
The git symbolic-ref
allows us to read, modify and delete symbolic refs
For more information on the flags, check out --quiet
and --short
As you can see from the above example, when the above command is run, it spits out the branch name.
The git rev-parse
is used as a safety net in scenarios like detached heads where we might need to pick out params from a lot of info
[kunalnagar] at ~/Documents/Code/personal-main (updates-v3)
=> git symbolic-ref --quiet --short HEAD 2> /dev/null || git rev-parse
updates-v3
Step 3
Cool, now we have the branch name. Now we just need to set the bash variable PS
to show our minimal prompt
PS1="\n[\u] at \w";
\n
: New line
\u
: Current user (name)
\w
: Path relative to home (notice the tilda in the path names in the screenshots)
PS1+=" \$(git_prompt)";
This appends the branch name in parentheses (if it’s a git repo)
PS1+="\n=> ";
Just a new line. With a short arrow.
And we’re done! Hope this made sense. Bash scripting is fun. A side project I’m working on is to transition my SCSS compilation to CSS using Makefiles. Will post my findings soon.