Когда использовать косую черту в gitignore

108

Я пытаюсь более четко понять .gitignoreсинтаксис, в частности, что касается https://github.com/github/gitignore gitignores.

Я вижу, что ведущая косая черта используется только для сопоставления имен путей относительно местоположения .gitignoreфайла (из http://git-scm.com/docs/gitignore ):

Начальная косая черта соответствует началу имени пути. Например, «/*.c» соответствует «cat-file.c», но не «mozilla-sha1 / sha1.c».

Но что произойдет, если я уберу начальную косую черту? Насколько я понял, есть два случая:

  1. Если в шаблоне нет косой черты (или он содержит только конечную косую черту, что означает, что он должен соответствовать каталогу), поиск выполняется внутри всего дерева каталогов. Например, шаблон dir/будет соответствовать <root>/dir, <root>/a/dir, <root>/a/b/c/.../dirи т.д., где <root>есть место .gitignoreфайла.
  2. Если шаблон содержит косую черту, которая не находится в конечной позиции (это не последний символ), тогда она сопоставляется только с именами пути относительно .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файл (который я имею в виду только как пример, кстати) много моделей содержат слэш, так что они правильно подобраны против имен путей , начиная от корня, но есть несколько случаев, как downloader/и errors/что , если я не ошибаюсь, потенциально опасны, и их, вероятно, следует заменить на /downloader/и /errors/.

В качестве более общего вопроса, должен ли я всегда использовать ведущую косую черту для шаблонов, не содержащих косые черты (кроме конечной), когда я хочу выбрать путь, явно начинающийся с корня, и не использовать его для шаблонов, содержащих косые черты, или я должен всегда используйте начальную косую черту для ясности? Что вы думаете об этом?

Спасибо, что прочитали, и извините за длинный пост.

Swahnee
источник
8
Отличный вопрос и действительно хорошее объяснение, меня это тоже беспокоило, и ваше исследование прояснило мне ситуацию. Прочитав это, я бы сказал, что хорошей практикой является всегда начинать пути с косой черты, если они должны начинаться с корня, это делает намерение более очевидным.
Мартинсос
4
Спасибо :) Я согласен с вашим замечанием об использовании косой черты, чтобы сделать намерения более явными.
swahnee
8
Это должно быть частью документации .gitignore. Намного легче понять!
rmorrin
Я бы хотел, чтобы этот замечательный пост был разбит на разделы с вопросами и ответами ...
Баретт,

Ответы:

25

Просто хотел подвести итог для возможной быстрой справки в будущем - ведущая косая черта привязывает совпадение к корню. Таким образом, в приведенном ниже примере без косой черты подстановочный знак также исключает все, что находится внутри foo, потому что он будет *рекурсивно перемещаться вниз по дереву. Однако с /*он исключает все, кроме папки foo и ее содержимого:

$ cat .gitignore
/*
!/foo
солнцестояние333
источник
24

Вы полностью ответили на свой вопрос. Если вы посмотрите на репозиторий github / gitignore более внимательно, вы увидите, что в большинстве файлов используются несогласованные правила написания шаблонов; скорее всего, большинство из них были внесены людьми, которые не удосужились прочитать документацию и не протестировать вещи, как это сделали вы.

Так что, если это помогает: вы правы, будьте уверены.

Если вы видите ошибки в таких совместных проектах, как этот, не стесняйтесь поделиться своими знаниями. Есть даже прецедент, если вам нужно еще больше укрепить свою уверенность.

tne
источник