Когда использовать свинцовую косую черту в gitignore
Я пытаюсь лучше понять синтаксис .gitignore
, и в частности, что касается https://github.com/github/gitignore gitignores.
Я вижу, что ведущая косая черта используется для сопоставления только путей по отношению к расположению файла .gitignore
(от http://git-scm.com/docs/gitignore):
Ведущая косая черта соответствует началу пути. Например, "/*.c" соответствует "cat-file.c", но не "mozilla-sha1/sha1.c".
Но что происходит, когда я удаляю ведущую косую черту? Насколько я понял, есть два случая:
- Если шаблон не содержит косой черты (или содержит только конечную косую черту, что означает, что она должна соответствовать каталогу), поиск выполняется внутри всего дерева каталогов. Например, шаблон
dir/
будет соответствовать <root>/dir
, <root>/a/dir
, <root>/a/b/c/.../dir
и т.д., Где <root>
- это местоположение файла .gitignore
.
- Если шаблон содержит косую черту, которая не находится в конечной позиции (это не последний символ), тогда она сопоставляется только с именами путей относительно расположения файла
.gitignore
.
Вот примеры, которые я сделал для проверки этого поведения:
# Directory structure:
<root>
|- dir/
| |- test
|- src/
| |- dir/
| | |- test
test file is there only because Git does not track empty directories.
Первый тест:
# .gitignore
dir/
# git status
nothing to commit
Итак, Git игнорирует оба каталога dir
. Это соответствует случаю номер 1: шаблон не имеет косых черт (кроме конечного), поэтому Git просматривает все дерево каталогов, игнорируя все, что соответствует шаблону.
Второй тест:
# .gitignore
/dir/
# git status
Untracked files:
src/
Здесь Git игнорирует только каталог dir
непосредственно под корневым каталогом, благодаря ведущей косой чертой в шаблоне.
Третий тест:
# .gitignore
dir/*
# git status
Untracked files:
src/
Это согласуется с номером дела 2: шаблон имеет некоторую косую черту внутри него, поэтому он рассматривается как путь, начинающийся с корневого каталога.
Теперь настало время для настоящего вопроса. Давайте рассмотрим этот файл gitignore: например, если они игнорируют каталог downloader/
, они не игнорируют каждый отдельный каталог downloader
, найденный во всем дереве каталогов? Это то, что я задумал, так как раньше я видел около Git.
Итак, если у меня есть пользовательский модуль с каталогом downloader
внутри него, будет ли он неожиданно проигнорирован, а также обычный в корне Magento? Это немного ретрительный вопрос, потому что это на самом деле со мной произошло, создавая очень трудную ошибку.
Итак, в файле Magento .gitignore
(который я имею в виду только в качестве примера, btw) многие шаблоны содержат косые черты, поэтому они правильно сопоставлены с именами пути, начиная с корня, но есть несколько случаев, например downloader/
или errors/
, которые, если я не ошибаюсь, потенциально опасны и, вероятно, должны быть изменены на /downloader/
и /errors/
.
Как более общий вопрос, должен ли я всегда использовать старшую косую черту для шаблонов, не содержащих косых черт (кроме конечной), когда я хочу выбрать путь, явно начинающийся с корня, а не использовать его для шаблонов, содержащих слэши, или я должен всегда использовать ведущую косую черту для ясности? Что вы думаете об этом?
Спасибо за чтение и извините за длинный пост.
Ответы
Ответ 1
Вы полностью ответили на свой вопрос. Если вы посмотрите более внимательно на github/gitignore repo, вы увидите, что большинство файлов используют противоречивые правила о том, как написаны шаблоны; очень вероятно, что большинство из них были внесены людьми, которые не удосужились прочитать документацию и не проверить, как вы это делали.
Итак, если это помогает: вы правы, будьте уверены.
Если вы видите ошибки в таких совлокальных проектах, не стесняйтесь вкладывать свои знания. Там даже некоторый прецедент, если вам нужно еще больше повысить свою уверенность.
Ответ 2
Просто хотел подвести итоги для возможной быстрой справки в будущем - ведущая косая черта соответствует совпадению с корнем. Таким образом, в приведенном ниже примере без косой черты подстановочный знак также исключает все внутри foo, потому что он принимает *
и рекурсивно перемещается по дереву. Однако с /*
он исключает все, кроме папки foo и ее содержимого:
$ cat .gitignore
/*
!/foo