Is there a way in which I can see all the git repositories that exist on my machine? Any command for that?
-
3See [git-summary](https://github.com/MirkoLedda/git-summary). It is a bash script that both lists all repositories and outputs their status information. Disclaimer, I am one of the devs. – cagliari2005 Jan 18 '18 at 16:46
-
@cagliari2005: What about bare repositories? https://stackoverflow.com/questions/60064170/looking-for-folders-containing-valid-git-bare-repositories – Luciano Feb 04 '20 at 19:26
11 Answers
If you are in Linux find / -name ".git"
, otherwise there is no way, they are standard directories, just use your OS file/folder find program to find .git
named folders.

- 22,500
- 11
- 75
- 105
-
2On Windows (and I am sure Mac too) you could do something similar... just a search for directories named .git - which is what git uses to store its meta information. – cjstehno Jan 07 '10 at 14:07
-
3On Macs, the above command works too. (Unless you're running OS9 or earlier!) – Alex Feinman Jan 07 '10 at 14:46
-
1Any good shell scripts or small utility applications that implement this simple file search functionality and add repository status information to the list? Shouldn't be an issue to write a shell script to do so, but rather use well-adopted scripts than my own unoptimized hacks. – jmlane Jun 10 '11 at 17:06
-
7@jmlane `for d in \`find / -name ".git"\`; do cd $d/..; echo \`pwd\`:; git status; echo; done` – LJ VanKuiken Sep 26 '13 at 13:17
-
1find man page has solution. Similar to the accepted answer but using -prune to return faster without going into the .git directories. Without prune find would go into the .git folder and depending on the contents spend time searching inside unnecessarily. Man page solution follows "find repo/ \( -exec test -d '{}'/.svn \; -or \ -exec test -d {}/.git \; -or -exec test -d {}/CVS \; \) \ -print -prune Check it out. Edit out svn and cvs if not required – quiet_penguin Oct 29 '18 at 12:32
-
Some git repositories contain loads of files, so you really want to avoid descending into the .git folder. Also, the `-name ".git"` doesn't work for me, it has to be `-name "*.git"` to get a wildcard match (quoted to avoid it being expanded by the shell). I'd update the above command to: `find / -type d -name "*.git' -print -prune` – ketil Feb 06 '20 at 14:03
-
I know this is a 10 year old Q/A... However, I'm wondering why on macOS Sierra (my current OS could apply to others) does this submitted solution return the results twice? By that I mean once at that the expected "normal path" ```/Users/USER/somedir``` and then again at the "absolute" ```/System/Volumes/Data/Users/USER/somedir``` – BrettJ Feb 23 '20 at 14:58
-
1Windows users: You can use this command in `Git Bash`, which you might have installed. – PWL Jul 13 '20 at 08:11
ORIGINAL ANSWER: This works pretty well from Windows Powershell:
Get-ChildItem . -Attributes Directory+Hidden -ErrorAction SilentlyContinue -Include ".git" -Recurse
EDIT #1: -Filter is twice as fast as -Include. Here is that solution:
Get-ChildItem . -Attributes Directory+Hidden -ErrorAction SilentlyContinue -Filter ".git" -Recurse
EDIT #2: Keith E. Truesdell mentioned sending the output to a file. See his comment for that solution. I prefer console output. But his comment got me thinking that I prefer just the full path, not the whole mess that is returned by default. If you want that just the full path, use the following:
Get-ChildItem . -Attributes Directory+Hidden -ErrorAction SilentlyContinue -Filter ".git" -Recurse | % { Write-Host $_.FullName }
FINAL NOTE: The above solutions only return Git repositories under the current directory. If you want ALL repositories on a drive, you should run the command once from the root of each drive.

- 8,949
- 10
- 51
- 76
-
1
-
2Get-ChildItem : A parameter cannot be found that matches parameter name 'Attributes'. At line:1 char:28 – Dewald Swanepoel Jan 30 '17 at 09:33
-
@DewaldSwanepoel - I don't have any idea why you would see that error about the Attributes parameter. It is clearly in the documentation, and I have tried it now on several Windows / PowerShell version combinations. Windows 7, 8, and 10 all work with various versions of PowerShell for me. If you DO find out why the error is occurring, please share it here so we can learn :>) – bopapa_1979 Feb 24 '17 at 19:02
-
@EricBurcham - Bizarrely, it would seem that my Get-ChildItem command has no parameter called "Attributes". When I look at the MSDN page for the command, it is definitely there. When I look at the help on the command provided by "get-help Get-ChildItem -details", it makes no reference to the -Attributes parameter. My version of PowerShell is 2.0. The MSDN page is for 5.1. I never specifically installed any version. I just have what came standard with Windows 7 Pro. – Dewald Swanepoel Feb 28 '17 at 20:14
-
2@DewaldSwanepoel - You can DEFINITELY upgrade your PowerShell version. We do it with chocolatey. I am currently running PowerShell version 5.0 on Windows 7 at work. – bopapa_1979 Mar 15 '17 at 17:12
-
1Very useful and quick. I like the suppression of errors. I would also add the output to a file and to filter for only the "directory". `Get-ChildItem . -Attributes Directory,Directory+Hidden -ErrorAction SilentlyContinue -Include ".git" -Recurse | Out-File -FilePath C:\Dev\GitRepoList.txt` – Keith E. Truesdell Jun 03 '19 at 19:42
-
1@KeithE.Truesdell - I am pretty sure the "Directory+Hidden" attributes is inclusive, and will only search directories. Adding -Directory my be faster in newer versions of PowerShell. I'll go time it. EDIT - Adding the "-Directory" makes no material difference, as the documentation would indicate. However, adding the Directory Attribute as you suggest does make it slower. I'm have now idea why, but I tested it both ways with Measure-Command and all three with the additional Directory attribute were slower than all three without. – bopapa_1979 Jun 05 '19 at 19:47
-
The parameter `-Force` shows hidden files, so you can use `Get-ChildItem . -Name '.git' -Force -Recurse` Note that using `-Name` causes it to return a string instead of objects. You can get around this by using `where` like `gci . -Force -Recurse | where { $_.Name -eq ".git" }` – ninMonkey Apr 29 '20 at 10:09
-
@ninMonkey thanks for mentioning that -Force shows hidden files. However, it also shows System files and folders, and does not exclude directories. I prefer using the attributes, though this is certainly less to type. Also, using -Name instead of -Filter does return a string, as you mentioned, but it returns the relative rather than the full path. Season to taste, I suppose. I suppose a "best fast effort" might look like this: Get-ChildItem . -Attributes Directory+Hidden+!System -ErrorAction SilentlyContinue -Filter ".git" -Force -Recurse | % { Write-Host $_.FullName }. Or use -Name. – bopapa_1979 May 14 '20 at 21:43
On *nix, this will also find any --bare
repositories.
find / -name "*.git" -type d

- 131,293
- 12
- 98
- 101
-
4Bare repositories don't need to be named `name.git` thats just a convention, that I for example, don't follow. – Arkaitz Jimenez Jan 07 '10 at 14:09
-
3Given that bare repositories don't need to follow that naming convention, is there a universal way to `find` those repos? – jmlane Jun 10 '11 at 17:04
-
Very old post, but you could adapt [this](https://stackoverflow.com/questions/2020812/#comment92990529_2020820) and instead see if something like `git rev-parse --git-dir` succeeds. – Sean Allred Aug 17 '21 at 18:48
Git repositories all have HEAD
, refs
and objects
entries.
on GNU/anything,
find -name HEAD -execdir test -e refs -a -e objects \; -printf %h\\n
Just checking for .git
will miss many bare repos and submodules.
To go full-paranoid on the checking you can ask git to do all its own checks before printing,
find -name HEAD -execdir test -e refs -a -e objects \; \
-execdir sh -ec 'GIT_DIR=$PWD git rev-parse --absolute-git-dir 2>&-' \;
(edit: I thought the .git/config
file was necessary, turns out it's not, so the absolute minimum git init newrepo
is
mkdir -p newrepo/.git/{objects,refs}
echo ref: refs/heads/master >newrepo/.git/HEAD
)

- 55,082
- 5
- 77
- 137
On Linux and OS X the following command is possibly the fastest (ignoring repositories without .git
) when the root directory of find
is /
:
find / -name .git -exec dirname {} \; -prune
But for roots that have mostly repositories underneath, the following is probably the fastest (you may want to replace /
with .
or another root):
find / -type d -exec test -d {}/.git \; -prune -print
Quick explanation of the primaries of find
used (since no operators are present here, -and
is implicit, i.e., for each visited node primaries are evaluated left to right until one of them evaluates to false
):
-name
istrue
if the name matches (often, but not here, with wildcards)-exec
executes a command terminated by;
(which is escaped by\
to avoid interpretation by the shell), and istrue
if the return status is0
(i.e., OK). The current node is available as{}
(which needs no escaping)-prune
is alwaystrue
, and causes all child nodes to be skipped-type d
istrue
for directories-print
is needed here because if-exec
is present it is not implicitly appended

- 12,237
- 2
- 40
- 64
-
I timed your and my version of the first `find` on a big tree, and yours was faster by 3.6% (46.6 seconds vs 48.4), so, yes, faster, but not “much faster” (on a MacBook Pro 2018 with Big Sur) – Walter Tross Jan 18 '22 at 14:03
-
The second find command is interesting because it doesn't print .git dirs that are nested inside a .git dir. I'm worried about its performance though. The first command can be made much faster with `find / -name .git -exec dirname {} + -prune` – Johan Boulé Jan 18 '22 at 14:10
-
Was to late to edit my comment. There's no need of xargs. Only thing to change is replace `\;`with `+` so that a `dirname` process isn't started for every repository. You are right that in this case, I was wrong saying it's much faster. I tend to have a horror reflex everytime I see a find command not taking advantage of commands that accept file lists as arguments. – Johan Boulé Jan 18 '22 at 14:15
On Linux, a faster way would be:
locate -r "\.git$"
assuming you keep locate's database updated with sudo updatedb

- 61
- 1
- 2
-
Definitely, locate is faster, use it with precautions, see here: https://unix.stackexchange.com/questions/60205/locate-vs-find-usage-pros-and-cons-of-each-other – AjayKumarBasuthkar Dec 20 '17 at 06:24
-
i like this way but dont know how to interate through the list to check thirtd things. and: some of the path have spaces :-( eg; "list=$(locate...); for path in $LIST do echo $path; cd $path; git status; done' dont work – f b Apr 18 '23 at 18:45
A simple PowerShell version:
Get-ChildItem . -Recurse -Hidden .git

- 93
- 9
-
2This worked for me! Thank you! I did get some errors for a few locations it tried to access that running as a normal user the powershell script did not have access to, but upon further review, these were places I shouldn't be worried about anyway (ie - `C:\users\
\PrintHood` Also, I found it useful to add an output to a file and since I only cared about the path (as this script gets a bunch of info) to also filter only for the path/directory info. `Get-ChildItem . -Recurse -Hidden .git | Out-file -FilePath C:\Dev\GitRepoList.txt` – Keith E. Truesdell Jun 03 '19 at 19:26
Small variation from Eric Burcham's answer. That answer adds \.git to end, this one doesn't.
Get-ChildItem . -Attributes Directory+Hidden -ErrorAction SilentlyContinue -Filter ".git" -Recurse | % { Write-Host $_.Parent.FullName }
I use this command at the beginning of the day. It simply adds a few git commands to the above. For some reason, our git repository works best if one runs a fetch then pull, don't know why. And we have a lot of submodules for some reason. Anyway, put what you need in between the {}'s.
push-location; Get-ChildItem . -Attributes Directory+Hidden -ErrorAction SilentlyContinue -Filter ".git" -Recurse | % { cd $_.parent.fullname; write-host '*************'; $(get-location).path; git fetch; git pull; git checkout .; git clean -f; git submodule update; git status; write-host '*************'; write-host ' '; }; pop-location

- 1,228
- 1
- 18
- 29
On Linux, try this command with root permission:
find / | grep \\.git$
this just searchs every files that end with .git ... you can do it with searching tools in Windows, Linux etc...

- 2,525
- 3
- 30
- 54
-
7There is no point letting `find` output everything then filtering with `grep`. I would rather use `--name "*.git"` – Gregory Pakosz Jan 07 '10 at 14:18
-
2
-
14@Michel, you start 2 processes and make the first one transmit through a pipe the whole `/` tree for the second to grep, when the first one can do everything and avoid the huge useless IO use. Not a real difference for the user normally, but for big filesystems it might make a difference. – Arkaitz Jimenez Jan 07 '10 at 14:39
-
2any way, if you wanna use JUST find command, it's better to use -regex instead of -name ... in this case, use this command: sudo find / -regex '.*\.git' – Michel Gokan Khan Jan 07 '10 at 22:05
-
5
For Linux:
dir="/home/${USER}"
dir_not="${dir}/miniconda3"
find /home/aeug -type d -iname ".git" -o -path "${dir_not}" -prune | xargs -0 echo

- 2,537
- 2
- 21
- 33
Ubuntu
find catalogue/archaeology/ -path '*/objects' -execdir git -C '{}' rev-parse --git-dir \; 2>&-

- 309
- 2
- 10