Last active
March 2, 2025 18:37
-
-
Save Moarram/e76ae364b9469c62d5f51ef3673235db to your computer and use it in GitHub Desktop.
A Zsh function to get the quantity of each Git status, in the form of an associative array
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/zsh | |
git-status-counts() { | |
local -A counts=( | |
'STAGED' 0 # staged changes | |
'CHANGED' 0 # unstaged changes | |
'UNTRACKED' 0 # untracked files | |
'BEHIND' 0 # commits behind | |
'AHEAD' 0 # commits ahead | |
'DIVERGED' 0 # commits diverged | |
'STASHED' 0 # stashed files | |
'CONFLICTS' 0 # conflicted files | |
'CLEAN' 1 # clean branch 1=true 0=false | |
) | |
# Retrieve status | |
local raw lines | |
raw="$(git status --porcelain -b 2> /dev/null)" | |
if [[ $? == 128 ]]; then | |
return 1 # catastrophic failure, abort | |
fi | |
lines=(${(@f)raw}) | |
# Process tracking line | |
if [[ ${lines[1]} =~ '^## [^ ]+ \[(.*)\]' ]]; then | |
local items=("${(@s/,/)match}") | |
for item in $items; do | |
if [[ $item =~ '(behind|ahead|diverged) ([0-9]+)?' ]]; then | |
case $match[1] in | |
'behind') counts[BEHIND]=$match[2];; | |
'ahead') counts[AHEAD]=$match[2];; | |
'diverged') counts[DIVERGED]=$match[2];; | |
esac | |
fi | |
done | |
fi | |
# Process status lines | |
for line in $lines; do | |
if [[ $line =~ '^##|^!!' ]]; then | |
continue | |
elif [[ $line =~ '^U[ADU]|^[AD]U|^AA|^DD' ]]; then | |
counts[CONFLICTS]=$(( ${counts[CONFLICTS]} + 1 )) | |
elif [[ $line =~ '^\?\?' ]]; then | |
counts[UNTRACKED]=$(( ${counts[UNTRACKED]} + 1 )) | |
elif [[ $line =~ '^[MTADRC] ' ]]; then | |
counts[STAGED]=$(( ${counts[STAGED]} + 1 )) | |
elif [[ $line =~ '^[MTARC][MTD]' ]]; then | |
counts[STAGED]=$(( ${counts[STAGED]} + 1 )) | |
counts[CHANGED]=$(( ${counts[CHANGED]} + 1 )) | |
elif [[ $line =~ '^ [MTADRC]' ]]; then | |
counts[CHANGED]=$(( ${counts[CHANGED]} + 1 )) | |
fi | |
done | |
# Check for stashes | |
if $(git rev-parse --verify refs/stash &> /dev/null); then | |
counts[STASHED]=$(git rev-list --walk-reflogs --count refs/stash 2> /dev/null) | |
fi | |
# Update clean flag | |
for key val in ${(@kv)counts}; do | |
[[ $key == 'CLEAN' ]] && continue | |
(( $val > 0 )) && counts[CLEAN]=0 | |
done | |
echo ${(@kv)counts} # key1 val1 key2 val2 ... | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment