This is a simple, clean, informative git
status line for your bash
shell prompt. The git-status
script defines a function called __git_status()
that returns a string describing the current state of your local repository:
origin
/local
/tag
/detached
origin indicator- branch name/tag name/commit hash position indicator
- total untracked files:
…n
- total stashed changes:
*n
- total commits behind origin:
↓n
- total commits ahead of origin:
↑n
- total deleted files:
✖ n
- total added files:
✚ n
- total renamed files:
↪ n
- total staged files:
✔ n
- total unstaged files:
✎ n
A complex set of changes containing all these elements might produce a status line that looks something like:
origin/some-feature/mybranch …1 ↓2 ↑2 ✖ 1 ✚ 1 ↪ 1 ✔ 2 ✎ 1
though that doesn't really come up often. I rarely have more than 1 - 3 status indicators showing at any given time. ymmv.
Sourcing the git-status
file in your shell creates a bash
function called __git_status
that prints the status line. Use as you see fit.
Running all the git
commands sequentially in bash
is a bit slow though, sometimes pushing a full second for complex changes or a large number of files, so I reimplemented it in go
. The shell script will still fallback to the bash
version if the binaries aren't found.
The performance of the go
version is limited to the speed of the slowest git
command, generally git diff --name-only
to list changed files. Usually 100 - 200 milliseconds.
To enable the go
version, add git-status-darwin-amd64
and/or git-status-linux-amd64
to your path. git-status
will detect the correct platform automatically.
There's a Makefile
now... so adding more architectures is easy enough.
$ git checkout <some hash> && __git_status
detached/20528e7ad4
$ git tag v0.0.1 && __git_status
tag/v0.0.1
$ git init && __git_status
local/master
$ touch foo && __git_status
local/master …1
$ touch bar && __git_status
local/master …2
$ git add foo && __git_status
local/master …1 ✚ 1
$ git add bar && __git_status
local/master ✚ 2
$ echo "baz" > foo && __git_status
local/master ✚ 2 ✔ 1 ✎ 1
$ echo "baz" > bar && __git_status
local/master ✚ 2 ✔ 2 ✎ 2
Because it's a newly tracked file, it sees it as a new file without changes once the changes are staged.
$ git add bar && __git_status
local/master ✚ 2 ✔ 2 ✎ 2
$ git commit -am "commit" && __git_status
local/master
$ git mv bar baz && __git_status && git reset --hard
local/master ↪ 1
$ echo "baz2" >> bar && __git_status
local/master ✔ 1 ✎ 1
$ echo "baz" >> foo && __git_status
local/master ✔ 2 ✎ 2
$ git add foo && __git_status
local/master ✔ 2 ✎ 1
$ touch baz && __git_status
local/master …1 ✔ 2 ✎ 1
$ touch 00ntz && __git_status
local/master …2 ✔ 2 ✎ 1
$ git add baz && __git_status
local/master …1 ✚ 1 ✔ 2 ✎ 1
1 untracked file, 1 deleted file, 1 new file, 1 modified file, 1 file with unstaged changes, 4 total files
$ git rm -f foo && __git_status
local/master …1 ✖ 1 ✚ 1 ✔ 1 ✎ 1
$ git commit -am "commit" && __git_status
local/master
$ git remote add origin https://github.com/user/repo.git && git push -u origin master && __git_status
origin/master
$ ... && __git_status
origin/master ↓2
$ ... && __git_status
origin/master ↑2
local branch contains 2 commits origin doens't have and origin contains 2 commits local branch doesn't have...
$ ... && __git_status
origin/master ↓2 ↑2
local ahead 2 commits, origin ahead 2 commits, 1 untracked file, 1 deleted file, 1 new file, 2 modified files, 1 renamed file, 1 file with unstaged changes, 5 total files
$ ... && __git_status
origin/master …1 ↓2 ↑2 ✖ 1 ✚ 1 ↪ 1 ✔ 2 ✎ 1