Git Status Across Multiple Repositories on a Mac

2019-01-14 07:16发布

问题:

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.

回答1:

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



回答2:

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



回答3:

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.



回答4:

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


回答5:

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.



回答6:

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.



回答7:

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.



回答8:

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:



回答9:

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.



回答10:

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 



回答11:

@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