25

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
Cœur
  • 32,421
  • 21
  • 173
  • 232
ulver
  • 1,431
  • 16
  • 26

9 Answers9

19

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.

KyleMit
  • 45,382
  • 53
  • 367
  • 544
  • Digging up the past a little here, but could you add an explanation about how this works? – GPPK Jan 21 '20 at 10:03
  • 1
    @GPPK Find all `.git` directories below current folder, pipe to while loop to get a named variable, `cd` to each `$dir` and echo its `git status` while also showing that directory – OneCricketeer May 21 '21 at 19:48
6

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. enter image description here

reducing activity
  • 1,645
  • 1
  • 24
  • 50
mnagel
  • 5,938
  • 4
  • 25
  • 63
6

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
ephemient
  • 180,829
  • 34
  • 259
  • 378
3

There is also a shell script called multi-git-status that does this.

Simply use the mgitstatus command (with an optional directory name argument):

slhck
  • 30,965
  • 24
  • 125
  • 174
1

I think this will do the job for each repo

git status -uall

https://git-scm.com/docs/git-status

arccoder
  • 57
  • 5
0

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
David Hunt
  • 21
  • 2
0

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 .git recursively find all .git repositories
  • -print print the path of the .git directory
  • -execdir git status \; run git status in that diectory (the directory containing the git directory)
CervEd
  • 702
  • 6
  • 14
0
for rp in /srv/*/
do
  printf '\ec'
  cd "$rp"
  git status
  echo "${rp%/}"
  read
done

Example

Steven Penny
  • 82,115
  • 47
  • 308
  • 348
0

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).

Jakub Narębski
  • 268,805
  • 58
  • 209
  • 228