我该如何查看我机器上的所有git仓库?

179

有没有一种方法可以查看我机器上存在的所有git仓库?有没有相应的命令?


3
请参考git-summary,这是一个Bash脚本,既可以列出所有的代码库,还能输出它们的状态信息。免责声明:我是其中一名开发者。 - cagliari2005
@cagliari2005:裸仓库怎么样?https://stackoverflow.com/questions/60064170/looking-for-folders-containing-valid-git-bare-repositories - Luciano
11个回答

136

如果您使用Linux,请执行find / -name ".git"命令进行查找,否则只能使用您的操作系统文件/文件夹查找程序来查找以.git命名的文件夹,因为这些是标准目录。


2
在Windows上(我相信Mac也是如此),您可以执行类似的操作...只需搜索名为.git的目录-这是git用于存储其元信息的目录。 - cjstehno
3
在 Mac 上,上述命令也适用。(除非你运行的是 OS9 或更早的版本!) - Alex Feinman
1
有没有好的shell脚本或小型实用程序可以实现这个简单的文件搜索功能,并将存储库状态信息添加到列表中?编写一个shell脚本来完成这个任务不应该是问题,但最好使用广泛采用的脚本而不是我自己未经优化的hack。 - jmlane
7
@jmlane 的命令是:for d in \find / -name ".git"`; do cd $d/..; echo `pwd`:; git status; echo; done`。它的作用是在当前机器的根目录下查找所有名为 ".git" 的文件夹,并进入每个文件夹的上级目录,输出该目录的路径和 git 仓库的状态信息。 - LJ VanKuiken
1
找到 man 页面有解决方案。类似于接受的答案,但使用 -prune 来更快地返回结果,而不进入 .git 目录。如果没有使用 prune,find 将进入 .git 文件夹,并根据内容花费时间在其中进行不必要的搜索。下面是 man 页面的解决方案: "find repo/ ( -exec test -d '{}'/.svn ; -or
-exec test -d {}/.git ; -or -exec test -d {}/CVS ; )
-print -prune 试试看吧。如果不需要 svn 和 cvs,请将其删除。
- quiet_penguin
显示剩余3条评论

65
这在Windows Powershell中非常有效:
Get-ChildItem . -Attributes Directory+Hidden -ErrorAction SilentlyContinue -Include ".git" -Recurse

编辑 #1:筛选(Filter)比包含(Include)快两倍。这是解决方案:

Get-ChildItem . -Attributes Directory+Hidden -ErrorAction SilentlyContinue -Filter ".git" -Recurse

编辑 #2: Keith E. Truesdell 提到了将输出发送到文件的方法,请查看他的评论以获得该解决方案。我更喜欢控制台输出,但他的评论让我想到我只需要完整路径,而不是默认返回的一堆信息。如果你只想要完整路径,可以使用以下代码:

Get-ChildItem . -Attributes Directory+Hidden -ErrorAction SilentlyContinue -Filter ".git" -Recurse | % { Write-Host $_.FullName }
FINAL NOTE: 以上解决方案仅返回当前目录下的Git代码库。如果要获取驱动器上的所有代码库,则应在每个驱动器的根目录下运行一次该命令。

1
非常适用于Windows用户! :) - Felix Feliciant
2
Get-ChildItem:找不到与参数名“Attributes”匹配的参数。 在第1行的第28个字符处。 - Dewald Swanepoel
2
@DewaldSwanepoel - 您绝对可以升级您的PowerShell版本。我们使用chocolatey来进行此操作。我目前在工作中使用Windows 7运行PowerShell版本5.0。 - bopapa_1979
1
非常有用且快速。我喜欢错误抑制功能。 我还会将输出添加到文件中,并过滤只包含“目录”的内容。Get-ChildItem . -Attributes Directory,Directory+Hidden -ErrorAction SilentlyContinue -Include ".git" -Recurse | Out-File -FilePath C:\Dev\GitRepoList.txt - Keith E. Truesdell
1
@KeithE.Truesdell - 我非常确定“Directory+Hidden”属性是包容的,只会搜索目录。在较新版本的PowerShell中添加-Directory可能会更快。我将去测试一下。编辑-如文档所示,添加“-Directory”没有实质性的差别。然而,像你建议的添加目录属性确实会使它变慢。我不知道为什么,但我用Measure-Command测试了两种方式,所有三个带有额外目录属性的都比没有的慢。 - bopapa_1979
显示剩余4条评论

24

在*nix系统上,这也将找到任何--bare仓库。

find / -name "*.git" -type d

4
裸库不需要被命名为 name.git,那只是一种约定。例如,我就没有遵循这个约定。 - Arkaitz Jimenez
3
鉴于裸仓库不需要遵循特定的命名约定,是否有一种通用方法可以"查找"这些仓库呢? - jmlane
非常老的帖子,但您可以适应这个,并尝试查看类似git rev-parse --git-dir是否成功。 - Sean Allred

17

Git仓库都包含HEADrefsobjects条目。

在GNU/任何系统上,

find -name HEAD -execdir test -e refs -a -e objects \; -printf %h\\n

仅检查 .git 可能会漏掉许多裸仓库和子模块。

如果想要完全做到检查,请在输出之前要求 git 进行所有自己的检查。

find -name HEAD -execdir test -e refs -a -e objects \; \
      -execdir sh -ec 'GIT_DIR=$PWD git rev-parse --absolute-git-dir 2>&-' \;

(编辑:我以为.git/config文件是必须的,结果证明不是,所以最小化的git init newrepo命令是)

git init newrepo是最少步骤来初始化一个Git版本库的命令。
mkdir -p newrepo/.git/{objects,refs}
echo ref: refs/heads/master >newrepo/.git/HEAD

)

=>

)


那最后一点对我来说是新的。不知道它是那么简单的。 - Mad Physicist

11
在Linux和OS X上,以下命令可能是最快的(忽略没有.git的存储库),当find的根目录为/时:
find / -name .git -exec dirname {} \; -prune

但对于主要存储库位于根目录下的情况,以下方法可能是最快的(您可以将 / 替换为 . 或其他根目录):

find / -type d -exec test -d {}/.git \; -prune -print

对于find命令中使用的primaries的快速解释(由于此处没有operators,因此-and是隐含的,即对于每个访问的节点,primaries从左到右进行评估,直到其中一个评估结果为false):

  • -name:如果名称匹配,则为true(通常使用通配符,但不在这里)
  • -exec:执行以;终止的命令(该分号可以通过\进行转义,以避免被Shell解释),如果返回状态为0(即OK),则为true。当前节点可用作{}(无需转义)
  • -prune:始终为true,并导致跳过所有子节点
  • -type d:对于目录为true
  • -print:在这里需要,因为如果存在-exec,它不会隐式追加

我对我们两个版本的第一个“查找”在一棵大树上进行了计时,你的速度比我的快3.6%(46.6秒对48.4秒),所以确实更快,但并不是“快很多”(在配备Big Sur的MacBook Pro 2018上)。 - Walter Tross
第二个查找命令很有趣,因为它不会打印嵌套在.git目录中的.git目录。但我担心它的性能。第一个命令可以通过使用“find / -name .git -exec dirname {} + -prune”来加快速度。 - Johan Boulé
来不及编辑我的评论了。不需要使用xargs。唯一需要更改的是将\;替换为+,以便不会为每个存储库启动一个dirname进程。 你说得对,在这种情况下,我说它快得多是错误的。每当我看到一个find命令没有利用接受文件列表作为参数的命令时,我就会有一种恐怖的反应。 - Johan Boulé

5
在Linux上,更快的方法是:locate -r "\.git$",假定您使用sudo updatedb来更新locate数据库。

无疑,locate更快,但使用时需注意,参见此处:https://unix.stackexchange.com/questions/60205/locate-vs-find-usage-pros-and-cons-of-each-other - AjayKumarBasuthkar
我喜欢这种方式,但不知道如何遍历列表以检查第三个元素。还有,一些路径中有空格:-( 例如:“list=$(locate…); for path in $LIST do echo $path; cd $path; git status; done'”是无法工作的。 - f b

3
一个简单的PowerShell版本:
Get-ChildItem . -Recurse -Hidden .git

2
这对我有用!谢谢!我确实在尝试访问一些位置时遇到了一些错误,因为普通用户运行的PowerShell脚本无法访问这些位置,但经过进一步审查,这些是我不必担心的地方(例如 - C:\ users \<username> \ PrintHood)。此外,我发现将输出添加到文件中很有用,由于我只关心路径(因为此脚本获取了大量信息),所以还要仅过滤路径/目录信息。Get-ChildItem . -Recurse -Hidden .git | Out-file -FilePath C:\Dev\GitRepoList.txt - Keith E. Truesdell

2
在Linux上,使用root权限尝试执行以下命令:
find / | grep \\.git$

这只是搜索以 .git 结尾的所有文件...你可以使用 Windows、Linux 等搜索工具来完成。


7
没必要让find输出所有内容再用grep筛选,我更倾向于使用--name "*.git" - Gregory Pakosz
2
@Gregory Pakosz:有什么区别吗? - Michel Gokan Khan
14
@Michel,你启动了两个进程并让第一个进程通过管道将整个/树传输给第二个进程的grep。但第一个进程可以完成所有操作,并避免了巨大而无用的IO使用。对于用户通常没有真正的区别,但对于大型文件系统可能会有所不同。 - Arkaitz Jimenez
2
无论如何,如果您想仅使用find命令,最好使用-regex而不是-name...在这种情况下,请使用此命令: sudo find / -regex '.*.git' - Michel Gokan Khan
5
@MichelKogan更好为什么? - Mark Amery

2

与Eric Burcham的回答略有不同,该回答没有在结尾添加“\.git”。

Get-ChildItem . -Attributes Directory+Hidden -ErrorAction SilentlyContinue -Filter ".git" -Recurse | % { Write-Host $_.Parent.FullName }

我在每天开始时使用此命令。它简单地添加了一些 git 命令到上面的命令中。由于某种原因,我们的 git 仓库最好先运行 fetch 然后再 pull ,不知道为什么。而且出于某种原因,我们有很多子模块。无论如何,在 {} 中放置所需内容。

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

对于 Linux:

dir="/home/${USER}"
dir_not="${dir}/miniconda3"
find /home/aeug -type d -iname ".git" -o -path "${dir_not}" -prune | xargs -0 echo 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接