如何获取带有子模块的 Git 存储库中所有文件的绝对路径?

How to get the absolute path of all files in a Git repository with submodules?

我正在尝试递归列出所有子模块中所有未跟踪的文件:

git submodule foreach --recursive git ls-files --others --exclude-standard --full-name

但这并没有列出绝对路径,它给出了子模块文件夹的相对路径。

我应该如何修改我的命令?

(注意:这是 "tool" 答案,而不是 "solution" 答案。也就是说,这个答案旨在为您提供 构建你想要的解决方案。)

使用git rev-parse --show-toplevel获取当前版本库的绝对路径。当然,在超级项目中执行此操作。这为您提供了任何路径前缀的第一部分——但现在您需要剩下的部分。

正如 the git submodule documentation 所说,在 foreach 中,您可以访问多个变量,包括 $path:

$path is the name of the submodule directory relative to the superproject ...

目前还不清楚(您必须自己测试)$path 在递归子模块的情况下是否是累积的。也就是说,如果超级项目 A 在路径 top/subB 下有子模块 B,当您在子模块 B 中时,$path 将是 top/subB。但是假设子模块 B 作为子模块 C 的超级项目, B自己的路径是contained/C。在子模块 C 中 $path 会是 top/subB/contained/C,还是只会 contained/C?1

无论如何,一旦你有了合适的前缀,只需使用类似 sed 的东西将其添加到前面,例如:

git ls-files --others --exclude-standard --full-name | sed "s,^,$prefix,"

其中 $prefix 设置为适当的前缀,可能只是 $path/。 (这假设 none 你的文件名包含一个嵌入的换行符;如果他们这样做,你的原始命令无论如何都会有麻烦。正如所写的那样,它还假设 none 你的前缀包含一个逗号 - 如果他们这样做, 使用 , 以外的字符,或使 $prefix 用反斜杠引用逗号。)


1逻辑表明这将是完整的路径;在不知道有多少子模块被递归到的情况下,相对路径并不完全可用。但是,相对路径更容易产生。

感谢 提出的想法。这有效:

git submodule foreach --quiet 'a=$(printf "$(git ls-files --others --exclude-standard --full-name|sed "s~^~$(pwd)/~")"; printf x); a=${a%x}; echo "$a"' | sed '/^\s*$/d'