git:在目录树中查找所有未提交的本地仓库

32

我在文件系统的某个位置有许多(10-15个)本地的git代码库,但它们都在 /data/ 文件夹中。

我想找到所有有未提交更改的文件夹。我该如何做?类似递归全局 git status 的变体。

我认为所有答案都错了。任何 git 命令只能在受 git 控制的文件夹中使用。我需要搜索这样的文件夹。

因此,我编写了这个脚本来实现这一点:

#!/usr/bin/env ruby
require 'find'
require 'fileutils'

#supply directory to search in as argument

@pat = ARGV[0]
(puts "directory argument required"; exit) unless @pat
Dir.chdir(@pat)
Find.find(@pat) do |path|
  if FileTest.directory?(path)
    Dir.chdir(path)
    resp = `git status 2>&1`
    unless resp =~ /fatal|nothing to commit \(working directory clean\)/i
      puts "#{'#'*10}\n#{Dir.pwd}#{'#'*10}\n#{resp}"
      Find.prune
    end

    Dir.chdir(@pat)
  end
end
13个回答

30

基于这个gist,介绍如何打印当前文件夹下所有仓库的git状态:

find . -type d -name '.git' | while read dir ; do sh -c "cd $dir/../ && echo -e \"\nGIT STATUS IN ${dir//\.git/}\" && git status -s" ; done

find 命令是您的好朋友,以及一些 shell 魔法。


1
这里稍微挖掘一下过去,你能否添加一个关于这个如何工作的解释? - GPPK
2
@GPPK 在当前文件夹下查找所有的.git目录,通过管道传递到while循环中获取一个命名变量,对于每个 $dir 使用 cd 命令进入该目录并输出其 git status 信息,同时显示该目录。 - OneCricketeer
这很好,但我会加上-maxdepth 2,这样会更快。最终优化命令:find . -type d -name '.git' -maxdepth 2 | while read dir ; do sh -c "cd $dir/../ && echo -e \"\nGIT STATUS IN ${dir//\.git/}\" && git status -s" ; done - Massimiliano Arione

8

还有一个名为multi-git-status的shell脚本可以实现这一功能。

只需使用mgitstatus命令(带有可选的目录名称参数):


7
我认为git没有这个功能,因此我(也)创建了一个脚本来完成这个任务:https://github.com/mnagel/clustergit 这里发布的代码片段的问题在于它们会在git status的输出格式发生变化时出错。我的脚本也有同样的问题(因为它基本上是以相同的方式工作),但至少你总是可以得到最新的版本。 enter image description here

我喜欢这个脚本! - ben
您可以通过使用“--porcelain”标志来避免在git status输出中出现破坏性更改。有关详细信息,请参阅手册页面。 - erb

6

类似这样的内容吗?

$ for i in /data/*/; do (cd $i && (echo $i; git status)); done
$ for i in /data/*/; do (cd $i \
> && (git status | grep -qx 'nothing to commit (working directory clean)' \
> || (echo $i && git status))); done
注:以上为it技术相关内容,涉及git命令的使用。

不要使用git-status。改用git-ls-files和git-diff / git-diff-files。 - Jakub Narębski
5
git-status 被称为“外壳程序”,旨在为用户服务,而不是脚本编写。其输出可能会随时更改,但不影响功能。 - Jakub Narębski
关于Jacob的术语... Git中“porcelain”一词是什么意思? - KyleMit

5

仅使用find命令

没有必要使用复杂的bash技巧,只需使用find命令即可。

find . -type d -name .git -print -execdir git status \;
  • find . -type d -name .git 递归查找所有 .git 存储库
  • -print 打印 .git 目录的路径
  • -execdir git status \; 在该目录中运行 git status(即包含 git 目录的目录)

1

2
那只完成了工作的一半。OP想要为每个repo运行状态命令。 - Uyghur Lives Matter

1
for rp in /srv/*/
do
  printf '\ec'
  cd "$rp"
  git status
  echo "${rp%/}"
  read
done

示例


0

虽然格式不是很花哨,但是这样怎么样?

find . -iname ".git" -type d | sed -rne "s|(.+)/\.git|echo \1;cd \1;git status;cd /data|p" | bash

0

你可以使用 "git ls-files --modified --deleted --exclude-standard" 列出所有修改和删除的文件 (--exclude-standard 可能不需要,但以防你想列出所有未被 --other 忽略的未知文件...)。然后你可以检查这个命令的输出是否为空。

或者你可以检查 "git diff --quiet HEAD" 的退出状态,如果你想检查 "git commit -a" 是否会捕捉到任何东西,或者检查 "git diff --cached --quiet HEAD" 是否会捕捉到任何东西 (或者它的其中一个管道相关命令:git-diff-filesgit-diff-index)。


0

安装 fd-find: cargo install fd-find https://github.com/sharkdp/fd#installation

find_nonclean_git () {
    fd -E Trash -H '^\.git$' ~ -x echo '{//}' | while read dir; do
        cd $dir
        echo $dir >/dev/null
        #git status -s | grep -c ^
        lnnum=$(git status -s | grep -c ^)
        #if [[ "$lnnum" != "0" ]]; then
        if (( $lnnum > 0 )); then
            echo $dir $lnnum
        fi
    done
}

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