10

Introduction

In order to check the status of git repositores, git status could be issued from the root of a repository.

C:\path\to\git_repositories\git_repo_1>git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working directory clean

If a directory consists of multiple, e.g. 50 git repositories

C:\path\to\git_repositories>dir

 Directory of C:\path\to\git_repositories

  .ssh
  git_repo_1
  ...
  git_repo_50
   0 File(s)
   51 Dir(s)

Nor

C:\path\to\git_repositories>git status .
fatal: Not a git repository (or any of the parent directories): .git

neither

C:\path\to\git_repositories>git status ./.
fatal: Not a git repository (or any of the parent directories): .git

is able to check the status of all repositories

Question

How to check the status of all git repositories at once?

030
  • 10,842
  • 12
  • 78
  • 123
  • To be honest I preferred the older form of the title, but for minor things like this it's probably not worth going back and bulk editing anyway. – Flexo Jul 06 '14 at 17:35

7 Answers7

13

You could use a for loop that changes into each directory, does git status and then changes back up:

for /f "tokens=*" %a in ('dir /ad /b') do cd %a & git status & cd ..

You need to double the percentages if you use this in a batch file:

for /f "tokens=*" %%a in ('dir /ad /b') do cd %%a & git status & cd ..

Edit:

As suggested by Cupcake, you could do this instead:

for /f "tokens=*" %a in ('dir /ad /b') do git --git-dir=%a/.git --work-tree=%a status

This feels like a more robust and flexible solution (e.g. you could adapt it more easily to work with a list of paths stored in a text file).

Matthew Strawbridge
  • 19,940
  • 10
  • 72
  • 93
  • Saving this command in a `status.bat file` into `C:\path\to\git_repositories>` and subsequently running it shows the status of all git repositories. Thank you. – 030 Jun 22 '14 at 15:59
  • 1
    @utrecht a better solution (instead of `cd` into each folder) is to simply tell Git where each repository is instead with `--git-dir=`, like `git status --git-dir=`. See the [official Git manual for details](https://www.kernel.org/pub/software/scm/git/docs/git.html#_options). –  Jun 22 '14 at 17:47
  • Actually, I'm not sure which solution would be faster, maybe the `cd` would actually be faster. –  Jun 22 '14 at 17:55
  • 1
    I goofed, if you're going to use `--git-dir` this way, then you also need to tell Git where the working copy directory is for each repository with `--work-tree=`, so for example: `git --git-dir=project/.git --work-tree=project status`. Otherwise, Git will think the current working directory is the working copy, so you'll end up with incorrect results. –  Jun 22 '14 at 18:56
  • @Cupcake changing the content of the status.bat to `for /f "tokens=*" %%a in ('dir /ad /b') do git --git-dir=%%a/.git --work-tree=%%a status` works as well. Thank you. – 030 Jun 22 '14 at 19:15
  • Using the `-C` key this becomes even shorter : `for /f "tokens=*" %a in ('dir /ad /b') do git -C %a status` or for bash: `for a in */; do git -C $a status; done` In order to keep track on which sub-directory it is reporting on, I did the following: `for a in */; do echo '--------------------------------------------------------------------------------'; echo $a; git -C $a status; done` – Adrian Nov 30 '17 at 07:48
11

I went with:

find . -name .git -execdir bash -c 'echo -en "\033[1;31m"repo: "\033[1;34m"; basename "`git rev-parse --show-toplevel`"; git status -s' \;

I think it's nicer because treats directories recursively.

Edited to show the name of the repo in a cleaner way.

Fernando Crespo
  • 484
  • 6
  • 17
  • Just checking, this wouldn't fetch, correct? So if there is new stuff on the remote then this wouldn't catch it? – Jazz Weisman Aug 16 '21 at 15:57
  • Also important to note that with the -s flag git status will not show if, eg, you are behind the remote by n commits (a main use case for me). My modified version of yours is as follows: find . -name .git -execdir bash -c 'echo -en "\033[1;31m"repo: "\033[1;34m"; basename "`git rev-parse --show-toplevel`";git fetch; git status -s -b' \; My only problem with it at this point is that the -b flag shows info even when up to date. With that fixed I would think this was perfect. – Jazz Weisman Aug 16 '21 at 16:15
4

If you are a kind of a tool-guy, you could use a little helper called RepoZ I wrote recently (and still write).

I answered a quite similar question in more detail here.

Here's a screenshot from the current development stage so hopefully you can see whether it seems helpful to you or not:

RepoZ

If you are wondering what that strings like +45 ~403 -88 mean - they are condensed status strings telling you whether there are commits to fetch or push and whether there are added/modified/deleted files locally. More detail on the project site on GitHub

Waescher
  • 5,361
  • 3
  • 34
  • 51
3

Borrowed from coderwall - git status on all repos in folder:

find . -maxdepth 1 -mindepth 1 -type d -exec sh -c '(echo {} && cd {} && git status -s && echo)' \;
  • find . : to find everything in the current folder
  • -maxdepth 1 : so that it doesn't recurse into subdirs of the repos
  • -mindepth 1 : so that it skips the current directory (of depth 0)
  • -type d : only find directories
  • -exec sh -c : spawn a shell and give it a command
  • '(echo {} && cd {} && git status && echo)' : the command given to the shell
  • echo {} : echo the directory found by find
  • cd {} : cd into the directory found by find
  • git status -s : run the actual git status, with the -s (short) option
  • echo : echo an empty line, for readability
  • \; : semicolon to run shell for each of the found directories instead of passing them all to one shell as arguments

Also, you could make an alias in your bash_profile use the following with escaping to make it work:

alias gs_recursive='find . -maxdepth 1 -mindepth 1 -type d -exec sh -c "echo {}; cd {}; git status -s; echo" \;'
KyleMit
  • 30,350
  • 66
  • 462
  • 664
Thomas M
  • 319
  • 2
  • 6
  • Nice answer! For those who got error running it on Command Prompt or PowerShell, it's because you need to run it on Git Bash instead – Samuel T. Oct 03 '22 at 14:10
2

As of 2.34 the for-each-repo command allows running git commands across a list of repos defined in a multi-valued config.

Example config:

[myRepos]
  repo = /full/path/without/expansion/repo1
  repo = ../can/be/relative/repo2
[alias]
  all = for-each-repo --config=myRepos.repo

Then you can run git all status.

Allen
  • 478
  • 9
  • 21
  • Awesome tip! Any ideas on how to generate the list of `[myRepos]` programatically? – KyleMit Dec 30 '21 at 15:03
  • This is really helpful - it looks like the repo list needs to be in global .gitconfig, is there any way to externalize the list of repositories? – lonstar Jul 25 '23 at 09:50
  • It does not need to be in the global config; it just needs to be visible/accessible where ever you're trying to use the command or alias. – Allen Jul 26 '23 at 17:46
0

If you have a system that is made up of numerous Git repositories, that is possibly a situation for which the Google repo tool was created: https://code.google.com/archive/p/git-repo/

If you find yourself writing scripts to distribute Git commands over these repositories, you should probably switch to repo.

repo works with an (unfortunately) XML file called the "manifest.xml" which specifies the Git repositories that are in the workspace. For each repo specifies which branch and commit should appear; you can use repo to "pin" the Git repositories to particular versions, or to track heads.

If you have a repo workspace then

$ repo status

then repo will do pretty much what you're asking for: iterate over the Git repos and give you a status.

Kaz
  • 55,781
  • 9
  • 100
  • 149
0

Oof... git's design failed.

When I looked up this question, I was reminded of all the examples out there that use cd to jump into repos and then run git commands in there.

You need to use the options --git-dir= and --work-tree=

(Well... that's what I want to say anyway.)

When we use those options --git-dir is the .git directory in the repo and the --work-tree= value is the repo's root directory.

For example

Let's say we are in C:\, the repo we're interested in is at C:\workspace\foobar

To get it's status without doing barbaric cd manuevers:

git --git-dir=c:\workspace\foobar\.git --work-tree=c:\workspace\foobar\ status

or for the nice short status we all like.

git --git-dir=c:\workspace\foobar\.git --work-tree=c:\workspace\foobar\ status -s

So that's only a little more than double the typing, and we get to use some barely coherent git options.

Now that we know the civilised way...

What's more we haven't lowered ourselves to virtually banging rocks together and typing...

cd c:\workspace\foobar; git status -s

Why would we ever do that.

(seriously though, do the cd. It's very rare to even find a script doing the --git-dir/--work-tree nonsense. It's extremely poor user service and has all the hallmarks of 0% design thought.)

Now let's do reflog... (ok let's not.)

ocodo
  • 29,401
  • 18
  • 105
  • 117