# Improve a script to generally check status of several git repos

I've tried to write a bash script that gives me a general overview of the status of git repos I have cloned/created. It's not meant to replace git status by any means, but give an overview of several repos.

Keep in mind I'm not the most knowledgeable about bash scripting AND git, so I imagine there is a better way to do this:

#!/bin/bash
# Help from: http://www.leancrew.com/all-this/2010/12/batch-comparison-of-git-repositories/

index=0
gitrepos=()

#TODO: There has got to be a better way to add all these folders to the array
for d in ~/repos/*; do
gitrepos[(index+=1)]="$d" done #add other important folders gitrepos[(index+=1)]=~/.vim gitrepos[(index+=1)]=~/dot_files gitrepos[(index+=1)]=~/bin for d in "${gitrepos[@]}"; do
if [ -e $d ]; then cd$d
else
echo " Did not find repo: $d" continue fi reponame="basename$d"

ok=true
git fetch --quiet origin 2>/dev/null
if [ ! -z "git diff HEAD origin/HEAD 2> /dev/null" ]; then
echo " $reponame --> Out of sync with origin/HEAD" ok=false fi if [ ! -z "git ls-files --other --exclude-standard 2> /dev/null" ]; then echo "$reponame --> Untracked files present"
ok=false
fi
if [ ! -z "git diff --cached --shortstat 2> /dev/null" ]; then
echo " $reponame --> Changes to be committed" ok=false fi if [ ! -z "git diff --shortstat 2> /dev/null" ]; then echo "$reponame --> Changes to be staged/committed"
ok=false
fi
if $ok; then echo " OK -->$reponame"
fi
done

-
Have you tried fgit? It's served me well for years. Disclaimer: I'm the author. –  l0b0 Apr 3 '13 at 11:48

Yes there is a better way of filling an array. You can use globbing inside of array parens. Also I suggest being explicit about what you do in bash and use declare -a to declare arrays and later on declare for other variables

declare -a repos=(~/repos/* ~/.vim ~/dot_files ~/bin)


In case of adding stuff to an array, after it got created:

repos+=("more stuff" here)


Maybe you want to name you iterating variable more verbose, instead of d repodir or something.

Your first if contains a continue so you can emphasize on this one and just go on with no else. Also don't miss the double quotes in case of directory names with spaces in them. Also you should check for -d since you cd into it.

if [ -d "$d" ]; then echo "No repo at$d"
continue
fi
cd "$d"  [ ! -z "cmd" ] is more verbose than it needs to be. You can just do [ "cmd" ]. Read the "Arrays" chapter in the bash manpage. I attach my test file for this answer which also shows functions and some refactoring which allows to discard this ok variable. #!/bin/bash main() { local -a repos=(* /foo/bar) echo -e "repos:${repos[@]}"
for path in "${repos[@]}"; do check_repo "$path"
done
}

check_repo() {
local path="$1" local name="basename "$path""
local report=""
if [ ! -d "$path" ]; then echo -e "$name\n not a directory: $path" return fi cd "$path"
if [ "echo foo 2> /dev/null" ]; then
report+="\n oh oh"
fi
cd - > /dev/null
if [ -z "$report" ]; then report+="\n OK" fi echo -e "$name\$report"
}

main

-
Thanks for your comments! They have taught me quite a lot about bash. –  lawrensm Feb 19 '13 at 5:08
Me too. Never have read "Arrays" before. –  payload Feb 19 '13 at 17:46