tl;dr

I spend alot of time in a terminal working with git. If you're like me then you can save typing by customising your command-line prompt. I'm going to chat for a bit about why I built this, you may want to jump straight to the PS1 samples at the bottom.

Some background

My top 10 most frequently used commands (I've run this on my home desktop but it looks much the same elsewhere) are:

  1. git: 81
  2. cd: 68
  3. ls: 48
  4. fab: 46
  5. gatus: 35
  6. gadd: 22
  7. giff: 21
  8. gommit: 19
  9. ssh: 16
  10. la: 13

Git clocks in at the top by some margin. There are a few common operations. You'd expect cd, ls and la (which I've aliased to ls -lah) to rate highly and ssh is a vital tool. The fab command is used by Python's Fabric library (which I will write a separate post about at some point) and I use it for deploying code. That leaves gatus, gadd, giff and gommit which are aliases for git status, git add, git diff and git commit respectively.

More than a third of the commands I type are git commands!

A long while back I realised it's possible to change the text displayed in the prompt of your shell. A vanilla shell isn't very useful:

$

Chances are that your OS will display something more helpful by default. Likely it'll be some combination of your username, the machine's hostname and the current path.

adamnfish@Axlotl:/home/adamnfish$
^-username ^-host  ^-path

This is great because without typing any commands you can see who you are logged in as, which machine this terminal is open on and where you currently are, all without typing any commands.

But if your command-line usage is dominated by git then ideally you should set up the prompt to also give you some info on the state of the git repository. Something like this would be pretty handy:

adamnfish@Axlotl:/home/adamnfish (master)$
                                  ^-- current git branch

At work we have conventions with our git workflow that allows a team of developers to work together on a project and independently deploy features and fixes to various environments. It works extremely well but it is easy to muck it up by accidentally committing code to the wrong branch, which means that being able to see which branch you're on is incredibly useful.

Today I extended my PS1 to include information about the current status of the repository. I have been constantly running git status (or gatus) to find out if there are any uncomitted changes, or if there are staged changes ready to be committed.

I've chosen 3 unicode characters to represent the current state of the repository.

  • - you have made changes to a file in the repository
  • - you have changes staged and ready for commit
  • - both of the above (you have staged some but not all of your changes)

So now my command prompt looks something like the following:

PS1 screenshot

You can see how it displays changes in the current repository by appending the appropriate symbol to the git branch name while I work.

How to use it

note: I'm using bash for all these examples

Setting up your command prompt is really simple.

If you use a proper OS

You can probably just insert the following into a file that is loaded for every shell (like ~/.bashrc).

_git_status()
{
  # check if we're in a git repository
  if git rev-parse 2> /dev/null; then
    # show if there are changes pending
    if current_git_status=$(git status --porcelain | grep '^ [MD]' 2> /dev/null > /dev/null); then
      PENDING="y"
    fi
    # show if changes have been 'added' for commit
    if current_git_status=$(git status --porcelain | grep '^[MADRC]' 2> /dev/null > /dev/null); then
      STAGED="y"
    fi
    if [ "$PENDING" = "y" ] && [ "$STAGED" = "y" ]; then
        echo -n "◈"
    elif [ "$PENDING" = "y" ]; then
        echo -n "◇"
    elif [ "$STAGED" = "y" ]; then
        echo -n "◆"
    fi
  fi
}
export PS1='\u@\h:${PWD}\[$(tput setaf 4)\]$(__git_ps1 " (%s\[$(tput setaf 2)\]$(_git_status)\[$(tput setaf 4)\])")\[$(tput sgr0)\]$ '

If you use OSX (or the above doesn't work)

This snippet makes use of the __git-ps1 command which is provided by git's autocompletion functionality. This isn't enabled by default on OSX so you'll need to download the file and include it before the PS1 directive.

Run the following from the terminal:

$ cd ~
$ curl https://github.com/git/git/raw/master/contrib/completion/git-completion.bash -OL
$ mv {,.}git-completion.bash

Then add the following to your .bash_profile file.

# include git's bash completion
source ~/.git-completion.bash
_git_status()
{
  ... see above

If you use Windows

Lol.