Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Check git status of multiple repos

If you're like me you have a dir like ~/Workspace/Github where all your git repos live. I often find myself making a change in a repo, getting side tracked and ending up in another repo, or off doing something else all together. After a while I end up with several repos with modifications. This script helps me pick up where I left off by checking the status of all my repos, instead of having to check each one individually.

Usage:

git-status [directory]

This will run git status on each repo under the directory specified. If called with no directory provided it will default to the current directory.

#!/bin/bash
dir="$1"
# No directory has been provided, use current
if [ -z "$dir" ]
then
dir="`pwd`"
fi
# Make sure directory ends with "/"
if [[ $dir != */ ]]
then
dir="$dir/*"
else
dir="$dir*"
fi
# Loop all sub-directories
for f in $dir
do
# Only interested in directories
[ -d "${f}" ] || continue
echo -en "\033[0;35m"
echo "${f}"
echo -en "\033[0m"
# Check if directory is a git repository
if [ -d "$f/.git" ]
then
mod=0
cd $f
# Check for modified files
if [ $(git status | grep modified -c) -ne 0 ]
then
mod=1
echo -en "\033[0;31m"
echo "Modified files"
echo -en "\033[0m"
fi
# Check for untracked files
if [ $(git status | grep Untracked -c) -ne 0 ]
then
mod=1
echo -en "\033[0;31m"
echo "Untracked files"
echo -en "\033[0m"
fi
# Check for unpushed changes
if [ $(git status | grep 'Your branch is ahead' -c) -ne 0 ]
then
mod=1
echo -en "\033[0;31m"
echo "Unpushed commit"
echo -en "\033[0m"
fi
# Check if everything is peachy keen
if [ $mod -eq 0 ]
then
echo "Nothing to commit"
fi
cd ../
else
echo "Not a git repository"
fi
echo
done
@senrabc
Copy link

senrabc commented Mar 22, 2016

Thank you. Works great.

@CycleMost
Copy link

CycleMost commented Mar 31, 2016

Nice script. I added this part to also check for files that have not yet been pushed to origin/master:

        # Check for unpushed changes
        if [ $(git status | grep 'Your branch is ahead' -c) -ne 0 ]
        then
            mod=1
            echo -en "\033[0;31m"
            echo "Unpushed commit"
            echo -en "\033[0m"
        fi

@lmj0011
Copy link

lmj0011 commented Oct 15, 2016

@MirkoLedda
Copy link

MirkoLedda commented Jan 7, 2018

prettified fork here: https://github.com/MirkoLedda/git-summary (supports Linux, MacOS and Cygwin)

@rw251
Copy link

rw251 commented Mar 6, 2018

Prettified fork based on @MirkoLedda's version, but that also works on Windows (assuming git bash or equivalent): https://github.com/rw251/git-summary

@iamdevlinph
Copy link

iamdevlinph commented Jul 24, 2018

I published an npm package out of @rw251 's version. You can view it here. You can install it by npm i -g git-summary and the usage is just the same

@fboender
Copy link

fboender commented Jul 28, 2018

I've implemented something similar: https://github.com/fboender/multi-git-status/

It can scan arbitrarily deep sub-directories (~/Projects/customer1/somegitrepo, ~/Projects/customer2/otherrepo) and shows uncommitted changes, untracked files, branches that need pushing, pulling or that have no upstream and stashes.

@ryankhart
Copy link

ryankhart commented Dec 21, 2018

I love that you commented everything so well. As someone who's still learning bash, it helps explain what's going on without me having to look up what some of the syntax means.

@kitzelh
Copy link

kitzelh commented Apr 7, 2019

for x in $(find . -type d -name ".git"); do cd $(dirname $x); pwd; git status; done

@DaniSpringer
Copy link

DaniSpringer commented May 9, 2019

How to use this? git-status is not a command

@DaniSpringer
Copy link

DaniSpringer commented May 9, 2019

for x in $(find . -type d -name ".git"); do cd $(dirname $x); pwd; git status; done

This checks the first repo, then remains there and looks for other repos there, so it gives a bunch of "no such file..."

@ocarlsen
Copy link

ocarlsen commented May 21, 2019

for x in $(find . -type d -name ".git"); do cd $(dirname $x); pwd; git status; done

This checks the first repo, then remains there and looks for other repos there, so it gives a bunch of "no such file..."

Yeah it doesn't cd back out of the directory after going into it. If you're using Bash, this works:

for x in $(find . -type d -name ".git"); do pushd $(dirname $x); pwd; git status; popd; done

@DaniSpringer
Copy link

DaniSpringer commented May 21, 2019

for x in $(find . -type d -name ".git"); do cd $(dirname $x); pwd; git status; done

This checks the first repo, then remains there and looks for other repos there, so it gives a bunch of "no such file..."

Yeah it doesn't cd back out of the directory after going into it. If you're using Bash, this works:

for x in $(find . -type d -name ".git"); do pushd $(dirname $x); pwd; git status; popd; done

Hey @ocarlsen
one-liners have their beauty, but it looks hard to customize (for example, I set it to not print anything if the response is nothing to commit, working tree clean)

But that's great to have, too!

I currently use https://github.com/DaniSpringer/multi-git-status

Thanks,
Dani

@contexua
Copy link

contexua commented Oct 9, 2019

thanks, works wonderful - very simple - just checks one directory level. Anything else is a different script I think 'keep it simple'

@danspringer - use an editor to place this script in /usr/bin on linux, then chmod +x to allow it toe be execcutable

@burningTyger
Copy link

burningTyger commented Jan 21, 2020

@DaniSpringer I started using yours too. Is there a solution that would let me add specific repos to a list and only check those? My dev dir is somewhat cluttered and I'd rather selectively check the ones I'm interested in. Otherwise thank you.

@thorgeir93
Copy link

thorgeir93 commented Jun 10, 2020

for x in $(find . -type d -name ".git"); do cd $(dirname $x); pwd; git status; done

This checks the first repo, then remains there and looks for other repos there, so it gives a bunch of "no such file..."

Yeah it doesn't cd back out of the directory after going into it. If you're using Bash, this works:

for x in $(find . -type d -name ".git"); do pushd $(dirname $x); pwd; git status; popd; done

Simplified output version:

for x in $(find . -type d -name ".git"); do pushd $(dirname $x) > /dev/null; (set -x; git status -s $PWD); popd > /dev/null; done

Example usage:

[thorgeir@MEGAS thorgeir]$ for x in $(find . -type d -name ".git"); do pushd $(dirname $x) > /dev/null; (set -x; git status -s $PWD); popd > /dev/null; done
+ git status -s /home/thorgeir/github/thorgeir/linux_configs
 M st_terminal_config.h
+ git status -s /home/thorgeir/github/thorgeir/utils
+ git status -s /home/thorgeir/github/thorgeir/calendar_icelandic
?? cal_is/test_cal_is.py

@fraber
Copy link

fraber commented Dec 3, 2020

Great starting point!
However, I've got >200 repos, so I only want to show the modified stuff. Please see the code below.

#!/bin/bash                                                                                                                                                     

dir="$1"
pushd .

# No directory has been provided, use current                                                                                                                   
if [ -z "$dir" ]
then
    dir="`pwd`"
fi

# Make sure directory ends with "/"                                                                                                                             
if [[ $dir != */ ]]
then
    dir="$dir/*"
else
    dir="$dir*"
fi

# Loop all sub-directories                                                                                                                                      
for f in $dir
do
    # Only interested in directories                                                                                                                            
    [ -d "${f}" ] || continue

    # Check if directory is a git repository                                                                                                                    
    if [ -d "$f/.git" ]
    then
    cd $f
    if [ $(git status --porcelain | wc -l) -eq 0 ]
    then
        continue
    fi
    echo -en "\033[0;35m"
    echo "${f}"
    echo -en "\033[0m"
    git status --porcelain
    fi
done
popd

@DaniSpringer
Copy link

DaniSpringer commented Mar 24, 2021

@DaniSpringer I started using yours too. Is there a solution that would let me add specific repos to a list and only check those? My dev dir is somewhat cluttered and I'd rather selectively check the ones I'm interested in. Otherwise thank you.

Still need?

@Pablo1107
Copy link

Pablo1107 commented May 2, 2021

When using git worktree the .git on the branches directory is actually a file that redirects to the main repo, so I change this to check if .git exists whenever is a directory or a file.

        # Check if directory is a git repository
	if [ -e "$f/.git" ]
	then
		[...]
	else
		echo "Not a git repository"
	fi

@shopglobal
Copy link

shopglobal commented Aug 21, 2021

Great script thanks for sharing!
I decided to alter the "if" statement which checks/fixes path to an elif statement to stop a local error on Ubuntu.

The script runs fine, but without this alteration it showed a small console error about syntax on line 12 regarding double brackets. I am not a shell expert, but I like using scripts when possible to save time. This modification works without error. Saves me time updating large projects. My version of the script has some added logic exclusive for my projects, thanks again.

Here's my mod: https://gist.github.com/shopglobal/0b7a46613f2335f150de855e717396ca/revisions

Original (if):

# No directory has been provided, use current
if [ -z "$dir" ]
then
    dir="`pwd`"
fi

# Make sure directory ends with "/"
if [[ $dir != */ ]]
then
	dir="$dir/*"
else
	dir="$dir*"
fi

Modified (elif):

# No directory has been provided, use current
if [ -z "$dir" ]
then
    dir="`pwd`"

# Make sure directory ends with "/"
elif [ $dir != */ ]
then
	dir="$dir/*"
else
	dir="$dir*"
fi

@marouenes
Copy link

marouenes commented Jan 25, 2022

Maybe considering adding a help context would be nice :D. I can submit an improvement if it's fine.

@melMass
Copy link

melMass commented May 16, 2022

Thanks, for recursion you can replace line 70 with ./$0 "${f}"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment