How can I view all the git repositories on my machine?
Asked Answered
K

13

183

Is there a way in which I can see all the git repositories that exist on my machine? Any command for that?

Kibe answered 7/1, 2010 at 14:3 Comment(2)
See git-summary. It is a bash script that both lists all repositories and outputs their status information. Disclaimer, I am one of the devs.Yousuf
@cagliari2005: What about bare repositories? #60064670Varsity
H
138

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.

Hertha answered 7/1, 2010 at 14:4 Comment(8)
On 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.Weissman
On Macs, the above command works too. (Unless you're running OS9 or earlier!)Abbott
Any 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.Hebephrenia
@Hebephrenia for d in `find / -name ".git"`; do cd $d/..; echo `pwd`:; git status; echo; doneFilibeg
find 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 requiredMelancholy
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 -pruneZamindar
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/somedirInconsistent
Windows users: You can use this command in Git Bash, which you might have installed.Outpatient
E
66

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.

Eyeshade answered 30/6, 2015 at 17:7 Comment(9)
very useful for windows users! :)Letty
Get-ChildItem : A parameter cannot be found that matches parameter name 'Attributes'. At line:1 char:28Quinones
@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 :>)Eyeshade
@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.Quinones
@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.Eyeshade
Very 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.txtProgeny
@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.Eyeshade
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" }Streeter
@Streeter 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.Eyeshade
A
24

On *nix, this will also find any --bare repositories.

find / -name "*.git" -type d
Arthro answered 7/1, 2010 at 14:8 Comment(3)
Bare repositories don't need to be named name.git thats just a convention, that I for example, don't follow.Hertha
Given that bare repositories don't need to follow that naming convention, is there a universal way to find those repos?Hebephrenia
Very old post, but you could adapt this and instead see if something like git rev-parse --git-dir succeeds.Pythoness
P
17

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

)

Prize answered 15/10, 2017 at 18:25 Comment(1)
That last bit is new to me. Didn't know it was that simpleDapper
S
11

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 is true 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 is true if the return status is 0 (i.e., OK). The current node is available as {} (which needs no escaping)
  • -prune is always true, and causes all child nodes to be skipped
  • -type d is true for directories
  • -print is needed here because if -exec is present it is not implicitly appended
Siftings answered 6/12, 2017 at 14:11 Comment(3)
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)Siftings
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 {} + -pruneRivi
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.Rivi
C
5

On Linux, a faster way would be:

locate -r "\.git$"

assuming you keep locate's database updated with sudo updatedb

Cassaundracassava answered 28/7, 2017 at 12:38 Comment(2)
Definitely, locate is faster, use it with precautions, see here: unix.stackexchange.com/questions/60205/…Copeland
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 workImmure
S
3

A simple PowerShell version:

Get-ChildItem . -Recurse -Hidden .git
Seductress answered 29/3, 2018 at 13:43 Comment(1)
This 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\<username>\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.txtProgeny
D
2

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

Doriandoric answered 7/1, 2010 at 14:10 Comment(5)
There is no point letting find output everything then filtering with grep. I would rather use --name "*.git"Estrange
@Gregory Pakosz : What's the difference ?Doriandoric
@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.Hertha
any 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'Doriandoric
@MichelKogan better why?Whiffletree
G
2

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
Gitlow answered 4/11, 2019 at 22:17 Comment(0)
L
1

For Linux:

dir="/home/${USER}"
dir_not="${dir}/miniconda3"
find /home/aeug -type d -iname ".git" -o -path "${dir_not}" -prune | xargs -0 echo 
Lainelainey answered 20/3, 2018 at 10:18 Comment(0)
R
1

I wanted the answer to this and for it to be as fast as possible. In particular I want to search a home directory for workspaces with the following constraints:

  • home directories may have VMWare shared mounts in them. No need to search outside of the current filesystem
  • some directories are inaccessible to the user. These can be skipped
  • directory names starting with . can be skipped
  • nested git workspaces can be skipped

With this in mind, I am using this GNU find command:

find . \
    -mount \
    ! -type d -prune -o \
    ! -executable -prune -o \
    -name '.?*' -prune -o \
    -execdir test -f '{}/.git/HEAD' \; -print -prune

This takes care to prune directories from the search as early as possible. Also, once a directory is positively confirmed as a git workspace, then it too is pruned. This returns the list of workspaces almost immediately (34ms on my home directory).

If you're using BSD find (e.g. MacOS), this does the same thing:

find . \
    -mount \
    ! -type d -prune -o \
    ! -perm -g+x -prune -o \
    -name '.?*' -prune -o \
    -execdir test -f '{}/.git/HEAD' \; -print -prune
Ruddle answered 17/2 at 4:26 Comment(0)
B
-1

The simplest way was not yet listed: git config --get-all safe.directory

Blastocoel answered 5/1 at 10:7 Comment(0)
R
-2

Ubuntu

find catalogue/archaeology/ -path '*/objects' -execdir git -C '{}' rev-parse --git-dir \; 2>&-
Redwing answered 29/1, 2023 at 5:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.