10

I've got a folder, which contains about 10 subfolders each containing a separate git repo. So something like this:

MainFolder/:
-- GitRepoA/
-- GitRepoB/
-- GitRepoC/
-- GitRepoD/
-- etc.

I often want to check whats going on, specifically I would like a command which lists the output for git status for all subfolders in which something has changed. Does anybody know a solution for this? (I'm on Mac OSX by the way).

kramer65
  • 50,427
  • 120
  • 308
  • 488
  • 1
    Duplicate of [Check status of all git repositories at once](http://stackoverflow.com/questions/24352701/check-status-of-all-git-repositories-at-once). Seriously, like an **exact** duplicate. –  Jun 24 '14 at 18:23
  • Nevermind, that's the Windows solution, but I wouldn't be surprised if someone else already asked for an OS X or a *nix solution elsewhere. –  Jun 24 '14 at 18:26

8 Answers8

13

If you need recursion (or will work as well if you don't):

find . -name .git -type d -execdir git status \;

For each directory named .git will execute git status from within the directory that contains it (-execdir). Wow, exactly what you want.

You can append -prune too so as to not go further in subdirectories of a git project to be more efficient (but might skip git submodules—I have no ideas how submodules work I never use them):

find . -name .git -type d -execdir git status \; -prune
gniourf_gniourf
  • 44,650
  • 9
  • 93
  • 104
6

Iterate over each directory, and set the working directory and .git directory with the commandline options --work-tree and --git-dir respectively:

for x in *; do git --work-tree="$x" --git-dir="$x/.git" status; done
user229044
  • 232,980
  • 40
  • 330
  • 338
  • if you loose overview, which of subdirectories is show a warning, message etc: enhance the with some echo output .. for x in *; do echo " " && echo "EXT:$x" && git --work-tree="$x" --git-dir="$x/.git" status; done – Jörg velletti Jan 18 '23 at 10:42
1
find . -maxdepth 1 -mindepth 1 -type d -exec sh -c '(echo {} && cd {} && git status -s && echo)' \;

It works recursively. You can change maxdepth and mindepth for your requirements

hakki
  • 6,181
  • 6
  • 62
  • 106
1
git status **/* *

Where:

  • **/* = Every file inside a subdiretory
  • * = Every file in the root diretory
1

I tried all of the suggestions here, and none of them really worked for me for various reasons.

So here's what I have in my profile and I use it pretty often.

gitr () {
  for f in $(find . -type d -name .git | awk -F"/.git$" '{print $1}');  do
    echo
    echo "................................ (cd $f && git $*) ........................................."
    echo
    (cd $f && git $*)
  done
}

Snippets in code files are easily loaded in bash with the "." command, for instance:

   . gitr.sh # file containing gitr() function, if not in a profile file

Then I can run

gitr status

And I get something like:

................................ (cd ./dir0 && git status) .........................................

On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

................................ (cd ./dir1 && git status) .........................................

On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

................................ (cd ./dir2 && git status) .........................................

On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

................................ (cd . && git status) .........................................

On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

or

gitr log -c 1

or

gitr rev-parse --abbrev-ref HEAD
Bret Weinraub
  • 1,943
  • 15
  • 21
1

This code will give the subdirectory a name and show a compact status:

ls | xargs -i sh -c 'echo _______ {} ______ && cd {} && git status -s -uno && cd .. '
soundflix
  • 928
  • 9
  • 22
0

You can create a script. Perhaps also just create it as a function and place in .bash_profile.

#!/bin/bash

REPOS=(GitRepoA GitRepoB GitRepoC AnotherRepoA)

for R in "${REPOS[@]}"; do
    echo "Checking repo $R."
    pushd "$R" >/dev/null && {
        git status
        popd >/dev/null
    }
done

Place it in the main folder and run

bash script_name.sh

If your repos are in uniform, you can just do some things like:

shopt -s nullglob
REPOS=(GitRepo{A..Z} AnotherRepoA)

Or perhaps just

shopt -s nullglob
REPOS=(*)

Just as a function:

function check_repos {
    REPOS=(GitRepoA GitRepoB GitRepoC AnotherRepoA)

    for R in "${REPOS[@]}"; do
        echo "Checking repo $R."
        pushd "$R" >/dev/null && {
            git status
            popd >/dev/null
        }
    done
}
konsolebox
  • 72,135
  • 12
  • 99
  • 105
  • 1
    Is there a way to do this for every subfolder so that I don't have to manually define all folders? – kramer65 Jun 24 '14 at 15:10
0

I dealt with this by writing a shell script, mgit, that reads a hidden file .mgit in the current directory which contains a list of folders that are individual git repositories. It does something similar to this:

$ for d in */; do git -C $d status; done
holygeek
  • 15,653
  • 1
  • 40
  • 50