17

I have been searching for a solution to this for a while and have not found quite what I need.

I have several Git Repositories in a folder on my Mac (OSX 10.6) and would like a script or tool that will loop through all the repositories and let me know if any of them needs commiting.

This is my structure

Sites
  /project1
  /project2
  /project3

I want the tool to do a git status in Sites/project1, Sites/project2, Sites/project3 and let me know if any of them have changes or new files that need to be staged or committed.

The closest script I found that might be hackable is here, but even that script wouldn't run, and I get an error:

"syntax error near unexpected token `do"

which might have been written for *nix.

Michael
  • 8,362
  • 6
  • 61
  • 88
eapen
  • 579
  • 6
  • 15
  • 3
    OS X *is* Unix. ;) Did you copy the script directly? I don't mean to be "that guy", but it worked for me (i.e., I didn't get a syntax error when running it). – mipadi May 04 '10 at 12:52
  • Yep, I knew that but I figured my bash version was missing some special Unix feature. I just tried copied the "raw" code and it works now - so it probably had to do with my copying it from the webpage before. Thanks for confirming that it works. – eapen May 04 '10 at 15:02

11 Answers11

25

It seems that the question has been answered fine, but I wanted to throw in my two cents after working on the same thing.

I went closer to jcordasc's answer by using a simple bash script. I just did one thing a little different. Looking at the help docs for git you can set the git directory and working directory. This eliminates the need to 'cd' to the directories. Not that it really makes that much difference...

#!/bin/bash

for gitdir in `find ./ -name .git`; 
    do 
        workdir=${gitdir%/*}; 
        echo; 
        echo $workdir; 
        git --git-dir=$gitdir --work-tree=$workdir status; 
    done

Obviously his is more advanced/cleaner for how it shows the status'...

Woody2143
  • 443
  • 1
  • 4
  • 9
  • Honestly I would have much rather posted this as a comment to jcordasc's answer but damned if I could see how to accomplish that... – Woody2143 Jun 08 '10 at 16:45
  • 1
    You could just use `git -C $gitdir` instead of the `--gitdir` and `--work-tree` options. So the last line of the do block becomes `git -C $gitdir status;`. – Ryan Bennetts May 10 '17 at 07:49
12

There's a Python based program, uncommitted that sounds like it would do exactly what you want. There's no git support for it yet (just hg and Subversion), but you may be able to help the author implement git support in his app, or take his ideas as how to implement your stuff (he documents his finding method on the project page I linked to).

RyanWilcox
  • 13,890
  • 1
  • 36
  • 60
5

This is an older question, but I went and updated jcordasc's answer so it works with git 1.7.7.5, and I thought I may as well contribute it here:

https://gist.github.com/3018100

This version takes any path or paths as argument, and gives jcordasc's output for any git repository it finds anywhere in the file trees represented by the arguments. It also supports detection of unpushed and unmerged commits.

Andrew Roberts
  • 770
  • 2
  • 8
  • 13
5

Multiple repo status checking with jsut a single shell alias. No installation is required. All credits to: https://coderwall.com/p/grmruq/git-status-on-all-repos-in-folder

For bash:

alias gitstat='find . -maxdepth 1 -mindepth 1 -type d -exec sh -c "(echo {} && cd {} && git status -s && echo)" \;'
alias gitstatfull='find . -maxdepth 1 -mindepth 1 -type d -exec sh -c "(echo {} && cd {} && git status && echo)" \;'

or for Cshell

alias gitstat           'find . -maxdepth 1 -mindepth 1 -type d -exec sh -c "(echo {} && cd {} && git status -s && echo)" \;'
alias gitstatfull       'find . -maxdepth 1 -mindepth 1 -type d -exec sh -c "(echo {} && cd {} && git status && echo)" \;'
4

If you just want the status of files in local repos, something like this: http://gist.github.com/389478 should do the trick. You'll need to modify the pattern in the for loop to pickup whatever directories you want.

J. Cordasco
  • 836
  • 6
  • 15
  • I will try this soon, I was getting the same syntax errors when I first tried to run this using the "raw" mode, which might have to do with the line breaks. Once I give this a shot, I will let you know. – eapen May 06 '10 at 15:41
2

It took me a bit of time to get the code from @Andrew Roberts to work with an array of folders .. If you're having trouble with that too, check my fork at https://gist.github.com/3666392

Thanks for the great script @Andrew Roberts and @jcordasc .. just what I needed.

Jeremy Ferguson
  • 763
  • 6
  • 7
2

The same question also occurred to me today and other than this page, that I found very useful and with very good tips, I also came across the following blog post. It introduces a python script that does exactly that:

Usage: show_status [options]

Show Status is awesome. If you tell it a directory to look in, it'll scan
through all the sub dirs looking for a .git directory. When it finds one it'll
look to see if there are any changes and let you know. It can also push and
pull to/from a remote location (like github.com) (but only if there are no
changes.) Contact mike@mikepearce.net for any support.

Options:
  -h, --help            show this help message and exit
  -d DIRNAME, --dir=DIRNAME
                        The directory to parse sub dirs from
  -v, --verbose         Show the full detail of git status
  -r REMOTE, --remote=REMOTE
                        Push to the master (remotename:branchname)
  -p PULL, --pull=PULL  Pull from the master (remotename:branchname)

The whole thing is located on this git repo.

oxtay
  • 3,990
  • 6
  • 30
  • 43
2

Very late to the party, but I wrote a tool to do this for me. It's a simple shell script, and it can be found on Github.

It looks like this:

Projects/fboender/multi-git-status: Uncommitted changes; Projects/fboender/jerrybuild.tst: Needs push (doc, master); Projects/fboender/multi-git-status.bak: Needs push (master); Projects/fboender/tempita: ok; Projects/fboender/dirigent: Uncommitted changes Untracked files; Projects/flusso/boxes: ok; Projects/flusso/docker: ok; Projects/flusso/deployments: ok; Projects/flusso/backup: ok;

Michael
  • 8,362
  • 6
  • 61
  • 88
Ferry Boender
  • 668
  • 1
  • 7
  • 14
0

This is an easy way of doing such things in in a one-liner. I am missing one last step that I will add once I find it out (unless someone else know it).

For a git status you can do:

find ./Sites -name .git | awk '{ print "git --git-dir=" $1 " --work-tree " substr($1,1,length($1) - 4) " status" }'

then copy the output and execute it.

For a complete diff, you can run:

find ./Sites -name .git | awk '{ print "git --git-dir=" $1 " --work-tree " substr($1,1,length($1) - 4) " --no-pager diff" }'

The copy-paste things that you must do annoys me. It should be using also xargs in there, but somehow, git complains:

find ./Sites -name .git | awk '{ print "--git-dir=" $1 " --work-tree " substr($1,1,length($1) - 4) " --no-pager diff" }' | xargs git

If anyone knows how to fix the git complaint in this last command, please edit this answer.

Gabriel Petrovay
  • 20,476
  • 22
  • 97
  • 168
0

There is also a ruby gem for this that works as a git sub command: https://github.com/reednj/git-status-all

# install the gem    
gem install git-status-all

# use the status-all subcommand to scan the directory
git status-all 

git status all

Nathan
  • 11,938
  • 12
  • 55
  • 62
0

@oxtay 's answer is the prettiest, so I've modified it to make it even prettier: https://github.com/Flurrywinde/Git-Status

I also fixed some bugs and made it work even with some messed up repos that caused @Ferry Boender's to throw errors:

./git-ftp: ok 
./kphotoalbum: ls: cannot access './kphotoalbum/.git/refs/heads': No such file or directory
fatal: Not a git repository: './kphotoalbum/.git'
fatal: Not a git repository: './kphotoalbum/.git'
fatal: Not a git repository: './kphotoalbum/.git'
Uncommitted changes 
./SemanticForms: Uncommitted changes 
./git-big-picture: Uncommitted changes Untracked files 
./10-minute-vim-exercises: ok 
./moviemasher: Uncommitted changes 
./tumbdlwtf: Uncommitted changes 
./rotatezoomHTML5video: Uncommitted changes 
./tumbdl: Needs push (master) 
.: ls: cannot access './python/refs/heads': No such file or directory
fatal: Not a git repository: './python'
fatal: Not a git repository: './python'
fatal: Not a git repository: './python'
Uncommitted changes 
.: ls: cannot access 'mediawiki/refs/heads': No such file or directory
fatal: Not a git repository: 'mediawiki'
fatal: Not a git repository: 'mediawiki'
fatal: Not a git repository: 'mediawiki'
Uncommitted changes 
parser: ls: cannot access 'parser/.git/refs/heads': No such file or directory
fatal: Not a git repository: 'parser/.git'
fatal: Not a git repository: 'parser/.git'
fatal: Not a git repository: 'parser/.git'
Uncommitted changes 
./gundo.orig: Uncommitted changes 
./wikiteam: Uncommitted changes Untracked files

@Nathan's ruby one seems to have a bug, giving an [ERROR] when the repo is fine:

$ git status-all
yourls-popular-clicks-extended                                                     [ERROR]
undefined local variable or method `s' for "yourls-popular-clicks-extended":String
miniProxy                                                                         [master]
dmenu-4.6-kanon          M15U37                                                   [master]
freeCodeCamp                                                                       [ERROR]
undefined method `up_to_date?' for nil:NilClass

$ mgitstatus                       
./yourls-popular-clicks-extended: ok 
./miniProxy: ok 
./dmenu-4.6-kanon: Uncommitted changes Untracked files 
./freeCodeCamp: Untracked files

Notice how it says [ERROR] for yourls-popular-clicks-extended and freeCodeCamp. Mine and Ferry's get it right.

Mine also retains its colors if run as a sub-process of watch, which makes it convenient to be cleaning up your repos and see each one get ticked off in real-time.

Screenshot of mine in a tmux session where I'm cleaning up the repos

Flurrywinde
  • 111
  • 1