Объяснить соответствие шаблону gitignore

У меня есть следующее дерево каталогов:

> #pwd is the repo   
> tree -a
.
├── .git
│   |.....
├── .gitignore
├── README.md
├── f1.html
├── f2.html ... and some more html
├── images
│   └── river.jpg
>

У меня также есть следующее в моем .gitignore:

> cat .gitignore
*
!*.html
!images/*.*
>

Я хотел бы, чтобы все файлы в каталоге изображений были включены в репо. Но этого не происходит. Я получил его для работы, используя следующее в gitignore:

*
!*.html
!images*
!*.jp*g

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

В противном случае Git рассматривает шаблон как оболочку, подходящую для потребление fnmatch (3) с флагом FNM_PATHNAME: подстановочные знаки в шаблон не будет соответствовать/в пути. Например, "Документация/*. Html" соответствует "Документация/git.html", но не "Документация/ppc/ppc.html" или "tools/perf/Documentation/perf.html".

Ответ 1

Во-первых, сложная часть вашего вопроса - это первая строка в файле .gitignore:

*  // Says exclude each and every file in the repository,
   // unless I specify with ! pattern explicitly to consider it

Сначала рассмотрим первую версию вашего .gitignore.

  • * исключить каждый файл в репозитории.
  • !*.html разрешить все html файлы.
  • !images/*.* рассмотрите все типы файлов в папке с изображениями.

Чтобы включить все JPG/JPEG, вы могли бы просто добавить !*.jp*g в 3-ей строке, что сделало бы git рассмотрением всех jpg и jpeg независимо от любой папки, в которой находится этот файл. Но вы специально хотели только из папки изображений, а не только для jpg, любого типа файла в папке с изображениями. Давайте прочитаем некоторую документацию, относящуюся к ней, и в третьем разделе мы перейдем к части решения.


Git игнорировать шаблон относительно рассмотрения папки:

  • Шаблон, заканчивающийся только косой чертой. Если шаблон заканчивается на <dir-name>/, то git будет игнорировать файлы, содержащиеся в этом каталоге и во всех других подкаталогах. В качестве примера, приведенного в документах

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

    но также обратите внимание: если какой-либо шаблон соответствует файлу в исключенном каталоге, git не рассматривает его.

  • У шаблона нет слэша. Если вы указываете имя dir в списке игнорирования, которое не заканчивается косой чертой, git будет рассматривать его как просто шаблон, который может соответствовать любому файлу, имеющему этот путь.

    Если шаблон не содержит косой черты /, git рассматривает его как оболочку glob pattern и проверяет соответствие имени пути относительно расположение

  • Шаблон с косой чертой и специальным символом (*/?). Если шаблон заканчивается, как в первом примере, который вы дали, images/*.* Он работает так, как указано в документации

    Пример: "Документация/*. html" соответствует "Документация/ git.html", но не "Документация/ppc/ppc.html" или "tools/perf/Documentation/perf.html".


Решение

Учитывая третью точку git, следует рассмотреть все файлы в каталоге images для шаблона !images/*.*. Но это не так, потому что в документации говорится еще одна важная точка

Git не отображает исключенные каталоги

Из-за первой строки * сам каталог "images" игнорируется. Поэтому сначала мы должны сообщить git, чтобы рассмотреть каталог изображений, а затем дополнительные строки явно, чтобы рассмотреть другие типы (если необходимо).

*
!*.html
!images/                 // <- consider images folder
!images/*.*

Примечание. В последней строке рассматриваются все типы файлов только из каталога изображений, а не из любого из его подкаталогов. (3-я точка в разделе 2)