'git: Find all uncommitted locals repos in a directory tree
I have a bunch(10-15) of local git repositories somewhere on my filesystem, but all in the folder /data/
I want to find all/any folder that has uncommitted changes. How can I do that? Kind of like a recursive global git status variant.
All the answers got it wrong I think. Any git command only works within the folder that's under git control. I need something to search for such folders.
So instead I wrote this script that does this:
#!/usr/bin/env ruby
require 'find'
require 'fileutils'
#supply directory to search in as argument
@pat = ARGV[0]
(puts "directory argument required"; exit) unless @pat
Dir.chdir(@pat)
Find.find(@pat) do |path|
if FileTest.directory?(path)
Dir.chdir(path)
resp = `git status 2>&1`
unless resp =~ /fatal|nothing to commit \(working directory clean\)/i
puts "#{'#'*10}\n#{Dir.pwd}#{'#'*10}\n#{resp}"
Find.prune
end
Dir.chdir(@pat)
end
end
Solution 1:[1]
Adapted from this gist on how to print git status of all repositories under the current folder:
find . -type d -name '.git' | while read dir ; do sh -c "cd $dir/../ && echo -e \"\nGIT STATUS IN ${dir//\.git/}\" && git status -s" ; done
The find command is your friend, along with some shell magic.
Solution 2:[2]
I don't think git has this build in, thus I (also) created a script to do this: https://github.com/mnagel/clustergit
The problem with the snippets posted here is that they break as the output format of git status changes. My script has the same problem (as it basically works the same way), but at least you always get the latest version.

Solution 3:[3]
Something along these lines?
$ for i in /data/*/; do (cd $i && (echo $i; git status)); done $ for i in /data/*/; do (cd $i \ > && (git status | grep -qx 'nothing to commit (working directory clean)' \ > || (echo $i && git status))); done
Solution 4:[4]
There is also a shell script called multi-git-status that does this.
Simply use the mgitstatus command (with an optional directory name argument):
Solution 5:[5]
Solution 6:[6]
Using only find
There's really no need for fancy bash tomfoolery, just use find.
find . -type d -name .git -print -execdir git status \;
find . -type d -name .gitrecursively find all.gitrepositories-printprint the path of the.gitdirectory-execdir git status \;rungit statusin that diectory (the directory containing the git directory)
Solution 7:[7]
You can use "git ls-files --modified --deleted --exclude-standard" to list all modified and deleted files (--exclude-standard is not probably needed there, but just in case you want to list all unknown files that are not ignored with --other...). You can then check if the output of this command is empty.
Or you can check the exit status of "git diff --quiet HEAD" if you want to check if "git commit -a" would pick up anything, or "git diff --cached --quiet HEAD" if you want to check if "git commit" would pick anything (or one of its plumbing relatives: git-diff-files or git-diff-index).
Solution 8:[8]
for rp in /srv/*/
do
printf '\ec'
cd "$rp"
git status
echo "${rp%/}"
read
done
Solution 9:[9]
It's not very fancy for formatting but how about something like
find . -iname ".git" -type d | sed -rne "s|(.+)/\.git|echo \1;cd \1;git status;cd /data|p" | bash
Solution 10:[10]
I realise this is a pretty old thread now but in Windows 10 I couldn't get the WHILE/DO loop from @Tasos solution to work so I converted it to PowerShell.
This version also prints out the status of each uncommitted change as well as a bit of formatting for readability to group by folder names.
cd C:\Projects
$msgs = @()
gci ".git" -Directory -Recurse -Hidden | % {
$dir = $_
cd $dir\..
$gitMsgs = (git status -s)
if ( $gitMsgs ) {
$msgs += "$dir ****************************"
$msgs += $gitMsgs
$msgs += ""
}
}
$msgs | % { Write-Host $_ }
Solution 11:[11]
cargo install fd-find https://github.com/sharkdp/fd#installation
find_nonclean_git () {
fd -E Trash -H '^\.git$' ~ -x echo '{//}' | while read dir; do
cd $dir
echo $dir >/dev/null
#git status -s | grep -c ^
lnnum=$(git status -s | grep -c ^)
#if [[ "$lnnum" != "0" ]]; then
if (( $lnnum > 0 )); then
echo $dir $lnnum
fi
done
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow

