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

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

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

TMP / *
общественности / документы / ** / *

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

6 ответов

Решение

Это зависит от поведения вашей оболочки. 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

Обновление (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 и файлы в нескольких уровнях подкаталогов.

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

public/documents/

Следующее не делает то, что, кажется, все думают:

public/documents/**/*.obj

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

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

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

/tmp/*.log

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

/tmp/**/*.log

Но, выпуская git версии 1.6.0.4 и bash версии 3.2.17(1), кажется, что git вообще не поддерживает ** glob. Самая последняя справочная страница для gitignore тоже не упоминает **, так что это либо (1) очень новая, (2) неподдерживаемая, либо (3) какая-то зависимость от реализации глобализации в вашей системе.

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

tmp/*

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

/tmp

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

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

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

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


Смотрите https://github.com/git/git/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 Thn Thái Ngọc Duy <pclouds@gmail.com>


Simon Buchan также прокомментировал:

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

.gitignore на странице руководства упоминается:

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

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

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

public/documents/**/*

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

public/documents/*/*

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

tmp/**/*.log

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

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