Почему файл glob **/*. Cs в git grep не показывает все хиты *.cs?

Поэтому я хотел найти применение NLog в своем проекте и использовал для этого git grep, но он обнаружил еще несколько случаев, чем мне было нужно:

git grep NLog
GETA.Seo.Sitemap/Geta.SEO.Sitemaps.csproj:    <Reference Include="NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
GETA.Seo.Sitemap/Geta.SEO.Sitemaps.csproj:      <HintPath>..\packages\NLog.2.1.0\lib\net45\NLog.dll</HintPath>
GETA.Seo.Sitemap/Services/CloudinaryService.cs:                NLogger.Exception("Could not transform image", exception);
GETA.Seo.Sitemap/Services/CloudinaryService.cs:                NLogger.Warn("Url for cloudinary id was null");
GETA.Seo.Sitemap/Services/CloudinaryService.cs:                NLogger.Warn("Could not locate file object for cloudinary id in EpiServer");
 ....
 etc

Конечно, он нашел то, что искал, но я хотел отфильтровать только файлы, оканчивающиеся на.cs, Итак, я попытался сделать это:

git grep NLog **/*.cs
Web/Global.asax.cs:            NLogger.Info("Meny application start");

Всего один удар, и ни один из двух матчей, которые у меня были выше, не были перечислены. Я обнаружил, что это странно, и я, вероятно, неправильно понял глобальное совпадение git grep. Может ли кто-нибудь просветить меня?

1 ответ

Решение

(Терминологическое примечание, для любого, кто читает этот ответ: расширение таких вещей, как *.cs называется "сгущение", 1 с *.cs будучи "оболочкой". "Оболочка" - это ваш интерпретатор командной строки, который может быть sh, bash, zsh, dash, tcsh, и так далее. Git будет иметь собственную встроенную глобализацию. Расширенные символы называются подстановочными знаками, и они включают *, ?, а также [, Некоторые снаряды также лечат { особенно, что является проблемой при использовании имен Git reflog, таких как master@{yesterday} или же stash@{2}, Цитирование всегда доступно для всех этих.)

Проблема в этом конкретном случае - это может случиться или не случиться с другими людьми, в зависимости от того, какую оболочку они используют, и их обстоятельств - заключается в том, что они не защищены (без кавычек) * подвергается ракушке. Некоторые оболочки, такие как bash, расширяются или, по крайней мере, могут расширяться ** так же, как это делает Git, что означает "возвращаться в подкаталоги". Другие не могут или, в зависимости от настроек, не будут. 2

Если ваша оболочка расширяется **/*.cs включить имя Web/Global.asax.cs но не включать GETA.Seo.Sitemap/Services/CloudinaryService.cs (потому что это еще один уровень каталога), а когда Git получает имена, уже слишком поздно: подстановочный знак * персонажи ушли. Git никогда их не видит и не может делать их самостоятельно.

Простое решение - защитить символы подстановки от сбоев в оболочке, заключив их в кавычки:

git grep '**/*.cs'

(парные двойные кавычки - как в git grep "**/*.cs" - также работает в большинстве оболочек, и обратные слеши префиксов также работают при использовании вместо кавычек, как в git grep \*\*/\*.cs: просто защитите каждого уязвимого персонажа с помощью обратной косой черты). Для многих команд Git - это не так важно с git grep если вы не копируете старые коммиты - это хорошая идея, чтобы всегда защищать все символы подстановки, чтобы они передавались в Git, потому что Git расширит их против чего-то другого, кроме текущего рабочего дерева. Оболочка видит только рабочее дерево. 3)

Несмотря на то, что это зависит от оболочки, иногда подстановочный знак ничего не будет соответствовать, а затем будет пропущен. Например, если у вас нет каталога с именем sub а ты пишешь sub/* некоторые - не все - оболочки будут проходить буквальный текст sub/* на команду, которую вы побежали. 4 В этом случае, если команда является командой Git, она может снова выполнить свою собственную глобализацию. Не стоит полагаться на это, поскольку, как только есть что сопоставить, оболочка выполняет сопоставление, а не передает исходный подстановочный знак в программу.


1 Название "glob" сокращено от "global", и в очень ранних оболочках это было сделано внешней программой под названием glob, Ранние версии Unix работали на машинах с объемом памяти всего лишь 64 килобайта, поэтому для расширения возможностей внутри оболочки было мало места. Смотрите https://en.wikipedia.org/wiki/Glob_(programming) для получения дополнительной информации.

2 В bash расширение в стиле Git контролируется установкой переменной globstar,

3 Это может даже включать .git сам подкаталог репозитория, что вообще плохо. В bash это контролируется переменной dotglob,

4 В bash это контролируется failglob,

Обратите внимание, что bash предоставляет практически все возможные варианты поведения каждой возможной оболочки. Он пытается быть своего рода универсальной оболочкой. Конечно, это означает, что ему также нужны все эти управляющие переменные, что делает bash достаточно большим. Вы никогда не сможете запустить его на 64K PDP-11 без разделения I & D.

Другие вопросы по тегам