使用搜寻git储存库时,是否有一种方法可以排除某些路径/目录/文件git grep
?与--exclude
正常grep
命令中的选项相似吗?
我需要使用,git grep
因为grep
直接使用大型git存储库的速度太慢。
使用搜寻git储存库时,是否有一种方法可以排除某些路径/目录/文件git grep
?与--exclude
正常grep
命令中的选项相似吗?
我需要使用,git grep
因为grep
直接使用大型git存储库的速度太慢。
Answers:
这是不可能的,但是最近已经讨论过了。链接中的建议解决方法:
您可以将
*.dll
.gitignore文件放入git grep --exclude-standard
。
在git 1.9.0中,“魔术词” exclude
已添加到pathspec
s中。因此,如果要foobar
在除匹配文件之外的所有文件中进行搜索,*.java
可以执行以下操作:
git grep foobar -- './*' ':(exclude)*.java'
或使用!
“简短形式”排除:
git grep foobar -- './*' ':!*.java'
请注意,在v2.12之前的git版本中,使用exclude时pathspec
,必须至少具有一个“ inclusive” pathspec
。在上面的示例中,这是./*
(递归包括当前目录下的所有内容)。在git v2.13中,取消了此限制,并且git grep foobar -- ':!*.java'
无需使用即可./*
。
您还可以使用类似:(top)
(简短格式:/
:)的东西来包含仓库中的所有内容。但是随后您可能还希望将排除对象pathspec
也从顶部开始进行调整:(:/!*.java
否则,它将仅排除*.java
当前目录下的文件)。
有在一个允许所有的“咒语”一个很好的参考pathspec
,在git-scm.com(或只git help glossary
)。由于某些原因,kernel.org上的文档实际上已经过时了,即使它们通常在Google搜索中排在首位。
git grep clock.gettime -- './*' ':!arch/**' ':!drivers/**'
排除多个整个目录。我认为这不会阻止递归。
git grep
和git ls-files
from子目录,并且两个报告的文件名都相对于当前目录(即使使用':(top)'
include pathspec时)。这两个命令都--full-name
可以报告相对于根的名称,但默认情况下处于关闭状态。
更新:对于git> = 1.9,本机支持排除模式,请参见onlyone的答案。
这似乎向后看,但是您可以传递与您的排除模式不匹配的文件列表,git grep
如下所示:
git grep <pattern> -- `git ls-files | grep -v <exclude-pattern>`
grep -v
返回不匹配的所有路径<exclude-pattern>
。请注意,这git ls-files
也需要一个--exclude
参数,但这仅适用于未跟踪的文件。
您可以通过在存储库中创建属性文件来将文件或目录标记为二进制文件,例如
$ cat .git/info/attributes
directory/to/ignore/*.* binary
directory/to/ignore/*/*.* binary
another_directory/to/also/ignore/*.* binary
列出了二进制文件中的匹配项,但没有包含行,例如
$ git grep "bar"
Binary file directory/to/ignore/filename matches
other_directory/other_filename: foo << bar - bazz[:whatnot]
以@kynan的示例为基础,我制作了此脚本并将其放在的路径(~/bin/
)中 gg
。它确实使用git grep
但避免了某些指定的文件类型。
在我们的仓库中有很多图像,因此我排除了图像文件,如果我搜索整个仓库,则将时间缩短到1/3。但是可以很容易地将脚本修改为排除其他文件类型或geleralpatterns。
#!/bin/bash
#
# Wrapper of git-grep that excludes certain filetypes.
# NOTE: The filetypes to exclude is hardcoded for my specific needs.
#
# The basic setup of this script is from here:
# https://stackoverflow.com/a/14226610/42580
# But there is issues with giving extra path information to the script
# therefor I crafted the while-thing that moves path-parts to the other side
# of the '--'.
# Declare the filetypes to ignore here
EXCLUDES="png xcf jpg jpeg pdf ps"
# Rebuild the list of fileendings to a good regexp
EXCLUDES=`echo $EXCLUDES | sed -e 's/ /\\\|/g' -e 's/.*/\\\.\\\(\0\\\)/'`
# Store the stuff that is moved from the arguments.
moved=
# If git-grep returns this "fatal..." then move the last element of the
# arg-list to the list of files to search.
err="fatal: bad flag '--' used after filename"
while [ "$err" = "fatal: bad flag '--' used after filename" ]; do
{
err=$(git grep "$@" -- `git ls-files $moved | grep -iv "$EXCLUDES"` \
2>&1 1>&3-)
} 3>&1
# The rest of the code in this loop is here to move the last argument in
# the arglist to a separate list $moved. I had issues with whitespace in
# the search-string, so this is loosely based on:
# http://www.linuxjournal.com/content/bash-preserving-whitespace-using-set-and-eval
x=1
items=
for i in "$@"; do
if [ $x -lt $# ]; then
items="$items \"$i\""
else
moved="$i $moved"
fi
x=$(($x+1))
done
eval set -- $items
done
# Show the error if there was any
echo $err
注1
根据这个应该可以说出的东西git-gg
,并能称其为像一个普通的git命令:
$ git gg searchstring
但是我无法使它正常工作。我在中创建了脚本,~/bin/
并在中创建了git-gg
符号链接/usr/lib/git-core/
。
笔记2
该命令不能设为常规的sh
git-alias,因为它将在存储库的根目录中被调用。那不是我想要的!