Подтвердить что ты не робот

Разница в путях в файле .gitignore?

Я использовал git, но все еще путаюсь в пути к файлам .gitignore.

Итак, в чем разница между следующими двумя путями в файле .gitignore?

tmp/*
public/documents/**/*

Я понимаю, что tmp/* будет игнорировать все файлы и папки внутри него. Я прав? Но что означает этот второй путь линии?

4b9b3361

Ответ 1

Это зависит от поведения вашей оболочки. Git не работает, чтобы определить, как их расширить. В общем случае * соответствует любому отдельному файлу или папке:

/a/*/z
 matches        /a/b/z
 matches        /a/c/z
 doesn't match  /a/b/c/z

** соответствует любой строке папок:

/a/**/z
 matches        /a/b/z
 matches        /a/b/c/z
 matches        /a/b/c/d/e/f/g/h/i/z
 doesn't match  /a/b/c/z/d.pr0n

Объедините ** с * для соответствия файлам в целом дереве папок:

/a/**/z/*.pr0n
 matches        /a/b/c/z/d.pr0n
 matches        /a/b/z/foo.pr0n
 doesn't match  /a/b/z/bar.txt

Ответ 2

Если вы используете оболочку, такую ​​как Bash 4, тогда ** по существу является рекурсивной версией *, которая будет соответствовать любому количеству подкаталогов.

Это имеет смысл, если вы добавите расширение файла в свои примеры. Чтобы сопоставить файлы журналов сразу внутри tmp, вы должны ввести:

/tmp/*.log

Чтобы сопоставлять файлы журналов в любом подкаталоге tmp, вы должны ввести:

/tmp/**/*.log

Но тестирование с помощью git версии 1.6.0.4 и Bash версии 3.2.17 (1) -release, похоже, что git не поддерживает ** globs вообще. самая последняя страница man для gitignore не упоминает **, либо, так что это либо (1) очень новое, (2) неподдерживаемое, или (3) каким-то образом зависит от вашей системной реализации globbing.

Кроме того, в ваших примерах есть что-то тонкое. Это выражение:

tmp/*

... на самом деле означает "игнорировать любой файл внутри каталога tmp в любом месте исходного дерева, но не игнорировать сами каталоги tmp". При нормальных обстоятельствах вы, вероятно, просто напишите:

/tmp

..., который игнорирует один каталог tmp верхнего уровня. Если вам нужно хранить каталоги tmp, игнорируя их содержимое, вы должны поместить пустой файл .gitignore в каждый каталог tmp, чтобы убедиться, что git фактически создает каталог.

Ответ 3

Обновление (08-Mar-2016)

Сегодня я не могу найти машину, где ** не работает, как заявлено. Это включает OSX-10.11.3 (El Capitan) и Ubuntu-14.04.1 (Trusty). Возможно, git -ignore как обновлено, или, возможно, недавний fnmatch обрабатывает **, как ожидают люди. Таким образом, принятый ответ теперь кажется правильным на практике.


Оригинальное сообщение

** не имеет особого значения в git. Это функция bash >= 4.0, через

shopt -s globstar

Но git не использует bash. Чтобы узнать, что на самом деле делает git, вы можете поэкспериментировать с git add -nv и файлами на нескольких уровнях подкаталогов.

Для OP я пробовал каждую комбинацию, которую я могу придумать для файла .gitignore, и ничего не работает лучше этого:

public/documents/

Следующее не делает то, что каждый думает:

public/documents/**/*.obj

Я не могу заставить это работать независимо от того, что я пытаюсь, но, по крайней мере, это согласуется с git docs. Я подозреваю, что когда люди добавляют это к .gitignore, это работает случайно, только потому, что их файлы .obj - это точно одна поддиректория. Вероятно, они скопировали двойную звездочку из bash script. Но, возможно, существуют системы, в которых fnmatch(3) может обрабатывать двойную звездочку как bash can.

Ответ 4

Обратите внимание, что '**', когда он объединен с подкаталогом (**/bar), должен был измениться по своему поведению, поскольку примечание к выпуску для git1.8.2 теперь упоминает:

Паттерны в файлах .gitignore и .gitattributes могут иметь **/, как шаблон, который соответствует 0 или более уровням подкаталога.

например. "foo/**/bar" соответствует "bar" в "foo" или в подкаталоге "foo" .


См. commit 4c251e5cb5c245ee3bb98c7cedbe944df93e45f4:

"foo/**/bar" соответствует "foo/x/bar", "foo/x/y/bar"... но не "foo/bar".
Мы делаем особый случай, когда обнаруживается foo/**/ (и часть "foo/" уже сопоставлена), попробуйте сопоставить "bar" с остальной частью строки.

"Совпадение одной или нескольких каталогов" семантика может быть легко достигнута с помощью "foo/*/**/bar".

Это также делает "**/foo" совпадением "foo" в дополнение к "x/foo", "x/y/foo"..

Подписано: Nguyễn Thái Ngọc Duy <[email protected]>


Саймон Бьюкен также прокомментировал:

Текущие документы (.gitignore man page) довольно понятны, что не требуется подкаталог, x/** соответствует всем файлам (возможно пусто) x

В man-странице .gitignore упоминается:

Конечный "/**" соответствует всем внутри. Например, "abc/**" соответствует всем файлам внутри каталога "abc" по отношению к местоположению файла .gitignore с бесконечной глубиной.

Слэш, за которым следуют две последовательные звездочки, затем косая черта совпадает с нулевыми или более каталогами. Например, "a/**/b" соответствует "a/b", "a/x/b", "a/x/y/b" и т.д.

Ответ 5

Когда ** не поддерживается, "/" по существу является завершающим символом для подстановочного знака, поэтому, когда у вас есть что-то вроде:

public/documents/**/*

он, по сути, ищет два подстановочных элемента между косой чертой и сам не забирает слэш. Следовательно, это будет то же самое, что:

public/documents/*/*

Ответ 6

Это не работает для меня, но вы можете создать новый .gitignore в этом подкаталоге:

tmp/**/*.log

можно заменить на .gitignore в tmp:

*.log