4

我在主存储库中有两个子模块,它们与主存储库中的代码紧密耦合。以至于在执行 git grep 时,我希望主 repo 与这两个特定的子模块一起被 grep。我不能做一个完整的 git submodule foreach "git grep ... || true",因为我还有其他非常大的子模块,并且每个子模块可能需要 15-20 秒。

所以,我需要一个比 git submodule foreach 更具体的解决方案,它允许我指定要 grep 的特定子模块,以及 grepping 我的主 repo。

我的两个子模块是foosubmodules/bar

这是我目前的解决方案。这让我可以说git gpx -i something.*interesting,等等。我在创建 git 别名方面还是新手,所以我希望可以改进这个解决方案。

[alias]
    inr = "!f() { cd $1 && $2 ;}; f"
    gprs = "!f() { for r in $1; do git inr $r \"git grep $2\" | perl -pe \"s|^|$r/|\"; done ;}; f"
    gpx = "!f() { git grep $*; git gprs 'foo submodules/bar' \"$*\" ;}; f"

编辑:我发现的一个问题是我丢失了正则表达式周围的引号,所以我不能调用这样的东西:git gpx -i "foo bar",因为它被翻译成这个:git grep -i foo bar。我想不出一个干净的方法来避免这种情况。

4

1 回答 1

2

REDO:我已经将一个 bash 脚本与该脚本一起破解以进行分页(在底部提到),但注意到您的示例已经在搜索路径前添加了前缀。我稍微修改了您的别名,现在发现这对我有用:

[alias]
    gpx = "!f() { list=$1; shift; for r in . $list; do ( cd $r; git grep $@ | perl -pe \"s|^|$r/|\"; ); done ;}; f"

如果您使用子shell,那么您可以折叠“inr”功能“(cd $1; cmd; ...)”(因为它隔离了chdir),如果您添加一个“。” 然后它也会搜索超级模块。我用类似的东西测试了它

git --no-pager gpx 'foo submodules/bar' --color=always -nIE '\w+\(\w*\)' | less -R

它似乎与转义效果很好(将要使用git-rev-parse --sq-quote但似乎 git 已经为您处理了)。这似乎比下面列出的脚本更优雅,也许我可以使用带有函数前缀的别名样式并替换/简化很多功能。话虽如此,感谢您的展示!

试图gpx为寻呼机创建另一个别名,但是转义有点麻烦,所以我也只创建了另一个别名:

[alias]
   gpxp = "!f() { list=$1; shift; for r in . $list; do ( cd $r; git --no-pager grep --color=always $@ | perl -pe \"s|^|$r/|\"; ); done | less -R ;}; f"

然后就变成了

git gpxp 'foo submodules/bar' -nIE '\w+\(\w*\)'

注意:如果您遇到错误,这些错误将显示在 grep 文本结果中。

原件

我在转义和使用 git 别名时遇到了类似的问题。

我一直在编写一个小扩展git-submodule,允许您进行受限迭代。该功能的帮助位于git-submodule-ext foreach [-c | --constrain]帮助实施)中。安装说明在这里:自述文件

如果您希望将迭代限制为fooand something/bar,在您的超级模块中,您可以执行

git config scm.focusGroup 'foo something/bar'

然后做你的 greppage

git --no-pager submodule-ext foreach -t -r -c -k git grep 'expression'

或者,如果您使用别名安装,

git --no-pager tsfer -c -k git grep 'expression'

该选项是防止每个子模块在每次搜索后git --no-pager拉起。$GIT_PAGER--keep-going在脚本中添加了一个选项,这样如果 grep 什么都不返回(导致非零状态),它不会停止迭代。另一种解决方案是使用子模块文档中的示例git tsfer -c -k 'git grep "expression" || :',这等效地工作。

如果您的表达式很复杂,例如查找函数调用'\w+\(\w*\)',则需要将整个表达式括在双引号中:

git --no-pager tsferp -c -k "git grep -E '\w+\(\w*\)'"

如果转义是一个大问题并且您使用的是 bash,则导出一个函数以在迭代中使用(我修改的扩展脚本是 using bash,而不是 Git 的标准/bin/sh

greppage() {
    git grep -E 'some(really)?complex.*\(expression\)'
}
export -f greppage
git --no-pager tsfer -c -k greppage

希望有帮助。

注意:目前的一个缺点是可能很难确定匹配项位于哪个子模块中。可以通过以某种方式$name在子模块前面加上 来进行修复,但我查看了git grep's 选项并找不到类似的东西那。我稍微修改了命令并想出了这个,呃,'compact',命令:

git --no-pager sube -q foreach -t -r -c -k "echo [ \$name ]'\n'; git grep --color=always -E '\w+\(\w*\)'; echo '\n\n'" | less -R

这使得 foreach 安静(抑制 'Entering' 输出),并添加一些大括号和换行符,以便更容易看到子模块之间的划分。让我看看我是否可以为此创建一个函数/别名以使其更容易。

编辑:这是一起被黑的脚本,它不是那么优雅。我只是把它变成了一个 bash 函数来简化事情

git-greps() { git --no-pager sube -q foreach -t -r -c -k "git grep --color=always $(git rev-parse --sq-quote "$@") | perl -pe \"s|^|\$name/|\"" | less -R; }

例子

git-greps -nIE '\w+\(\w*\)'
于 2013-08-03T19:46:03.767 回答