使用"git submodule foreach"命令,可以跳过一些子模块吗?

6
假设我有10个子模块:
module/1
module/2
module/3
module/4
module/5
module/6
module/7
module/8
module/9
module/10

module/是顶层仓库。

我想要执行git submodule foreach 'git status',但是我不想为子模块4、6和7执行。

有没有一种方法可以做到这一点,类似于:

git submodule foreach --exclude="4 6 7" 'git status'

我尝试在命令块内部执行它,但是没成功。

git submodule foreach '
    if [[ $list_of_ignores =~ *"$displayname"* ]] ; then echo ignore; fi
'

更新 - 删除了错误地添加的--exclude="4 6 7"

但是我收到了一个错误,说eval [[: not found - 我猜这是因为它正在使用/bin/sh而不是/bin/bash?- 不确定...


git submodule 仍然是一个 shell 脚本。如果你愿意,你可以看看 cmd_foreach 是如何工作的,并将其复制到你自己的变体中并添加功能。不幸的是,大部分工作都发生在 git-submodule-helper 中,它不是一个脚本。 - torek
3个回答

12
根据文档,foreach 命令执行 shell 命令。
foreach [--recursive] <command>
    Evaluates an arbitrary shell command in each checked out submodule. The 
    command has access to the variables $name, $sm_path, $displaypath, $sha1
    and $toplevel

所以要使用Shell:

 git submodule foreach 'case $name in 4|6|7) ;; *) git status ;; esac'

如果你对该语法感到陌生,请查看bash的case语句语法。如果使用换行符写成脚本,上述代码将是:
case $name in # $name is available to `submodule foreach`
    4|5|6)
     ;;
    *)     # default "catchall"
     git status 
    ;;
esac

确定:excludes='4|6|7' git submodule foreach 'eval "case \$name in $excludes) ;; *) git status ;; esac"' - jthill
我注意到你的“请停止伪造证据”的评论。我没有这样做,也不明白为什么有人会这样做。我刚刚重新运行了它,结果得到了与我之前提到的完全相同的错误。第二点是 - 我似乎无法使用在子模块foreach 'cmd-block'之外设置的变量。因此,您在评论中的变量'excludes'似乎计算为空字符串。在重新阅读手册页面(您粘贴的)后,似乎暗示我们无法访问外部变量.... :( - code_fodder
2
注意:我刚刚删除了您复制并粘贴的“--exclude =“4 6 7””部分。那是错误留在那里的。所以现在它会给出我提到的错误-所以再次强调,不是假的,只是错误。所以我对您的“请停止”是“请停止草率下结论和认为人们最坏的一面”:) - code_fodder
所以最终找到了答案(从你给我的好起点开始)。单引号不会扩展传入的变量,因此必须使用双引号:excludes='4|6|7' git submodule foreach "eval \"case \$name in $excludes) ;; *) git status ;; esac\""。虽然我不同意被称为冒牌货,但问题无论如何都得到了很好的回答,因此选择其作为答案。 - code_fodder
1
这个shell是Ubuntu 18.04自带的,我认为相当不错。你的例子根本就不起作用。使用单引号不会扩展变量,你需要像我给你演示的那样使用双引号:)。我没有添加“无关的文本”。它不能是故意的,因为-如果你看一下我的“伪造”代码之前的代码,你会看到我删除的完全相同的文本-这被称为复制/粘贴错误,我只是不认为因为某人犯了一个错误就指责他伪造。我想你要找的词是:“是啊,我的错...对不起,伙计”。 - code_fodder
显示剩余2条评论

1
code_fodderjthill所说的基础上(添加一个反斜杠可以帮助命令正确运行,同时添加--recursive标志也是很好的),以下命令可以帮助排除不同的子模块,例如4、5和6,并对每个嵌套的子模块运行git status命令。
excludes='4|6|7' git submodule foreach --recursive "eval \"case \$name in \$excludes) ;; *) git status ;; esac\""

在Windows PowerShell中呢? - undefined

0

这可能是一种可怕的解决方案,但对于我的特定情况有效。

git submodule foreach --recursive 仅会迭代现有文件夹(包括非递归),因此我通常只需删除文件夹以跳过它们 (首先确保所有内容都已提交/存储!)

因此,在以下子模块结构的情况下:

tree
.
├── 1
├── 2
│   ├── 3
│   └── 4
├── 5
│   ├── 6
│   │   ├── 7
│   └── 8
└── 9

如果我想在除了“5”和其子模块之外的每个子模块上执行“foo”命令,我只需删除“5”文件夹即可:
rm -rf 5
git submodule --recursive foo             # 5, 6, 7, 8 won't be touched.
git submodule --update --init --recursive # Restore the removed folders.

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