Git Status Across Multiple Repositories on a Mac

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.

  • git pull/clone private repo using bash script only
  • Partial branch or partial merge or other way to help me to sync dotfiles?
  • What's the Windows command shell equivalent of bash's `true` command?
  • git diff - external viewer - get all diff results
  • How does git, for example, create the database they use?
  • Search for files in a git repository by extensions
  • Maven - Cannot create resource output directory in a shell script
  • How to add git remote repos name repeatedly in jenkins shell?
  • 11 Solutions collect form web for “Git Status Across Multiple Repositories on a Mac”

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

    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’…

    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.

    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.

    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)" \;'
    

    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.

    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.

    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.

    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;

    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

    @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

    Git Baby is a git and github fan, let's start git clone.