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/detachedorigin 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 ✎ 1though 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 ✎ 2Because 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 ✎ 11 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 ↑2local branch contains 2 commits origin doens't have and origin contains 2 commits local branch doesn't have...
$ ... && __git_status
origin/master ↓2 ↑2local 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