Разница в путях в файле.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