Подтвердить что ты не робот

Gitignore: игнорировать все файлы в иерархии папок, кроме одного определенного типа файла

Я хотел бы игнорировать все файлы ниже и в папке, кроме определенного типа файла, который может быть где-то в иерархии папок:

Пример

/Test
/Test/unknown/folder/structure/below

Теперь я хочу игнорировать все файлы в папке Test и ниже Test, за исключением некоторого файла css с именем layout.css, например:

/Test/layout.css
/Test/fileto.ignore
/Test/another/folder/ig.nore
/Test/in/a/unknown/folder/layout.css
/Test/in/a/unknown/folder/ignore.me

.gitignore следует игнорировать

/Test/fileto.ignore
/Test/another/folder/ig.nore
/Test/in/a/unknown/folder/ignore.me

Мой .gitignore файл не работает:

Test/
!layout.css

Любые предложения?

4b9b3361

Ответ 1

Мне удалось заставить ваш пример работать, поместив файл .gitignore в каталог Test/ со следующим содержимым.

*
!*/
!.gitignore
!layout.css

Ответ 2

Чтобы выполнить то, что вы хотите, вам нужно использовать некоторые отрицательные исключения.

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

Итак, если вы хотите добавить /Test/in/a/unknown/folder/layout.css в ваш репозиторий git, вам нужно будет выполнить неигрырование /Test/,/Test/in/,/Test/in/a/,/Test/in/a/unknown/, и/Test/in/a/unknown/folder/.

Затем, когда вы, наконец, попадаете в каталог с некоторыми игнорируемыми и некорректированными файлами, вам нужно будет указать их индивидуально следующим образом:

# Fille: .gitignore
!Test/
Test/*
!Test/layout.css
Test/fileto.ignore
!Test/another/
Test/another/*
!Test/another/folder/
Test/another/folder/*
!Test/in/
Test/in/*
!Test/in/a/
Test/in/a/*
!Test/in/a/unknown/
Test/in/a/unknown/*
!Test/in/a/unknown/folder/
Test/in/a/unknown/folder/ignore.me
!Test/in/a/unknown/folder/layout.css

Итак, когда вы запустите $ git add-all, вы увидите желаемые результаты:

$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   .gitignore
    new file:   Test/in/a/unknown/folder/layout.css
    new file:   Test/layout.css

Примечание. Вы можете найти объяснение, почему git add-all - лучший способ добавить файлы в репозиторий git в http://lexsheehan.blogspot.com/2014/05/git-add-update.html

Ответ 3

Довольно старый вопрос, но поскольку я боролся с этой проблемой, даже сейчас я решил, что поделился бы фактическим решением проблемы.

Дело в том, что вы не можете передавать пустые каталоги в Git, как если бы они были проигнорированы, это правило не относится к .gitignore.

От https://git-scm.com/docs/gitignore

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

Слэш, за которым следуют две последовательные звездочки, затем совпадение ноль или более каталогов. Например, "a/**/b" соответствует "a/b", "a/x/b", "a/x/y/b" и т.д.

** Совпадает со всем внутри - буквально все - файлы и каталоги.

Это приводит нас к другому вопросу в документах gitignore:

Дополнительный префикс "!" что отрицает шаблон; любой соответствующий файл исключенный предыдущим шаблоном, снова включается. Это не можно повторно включить файл, если родительский каталог этого файла исключено. Git не перечисляет исключенные каталоги для производительности причины, поэтому любые шаблоны на содержащихся файлах не имеют никакого эффекта, независимо от того, где они определены. Поместите обратную косую черту ( "\" ) перед первой "!" для шаблонов, которые начинаются с буквального "!" , например, "! Важно!.txt".

Если шаблон заканчивается косой чертой, он удаляется с целью после описания, но он найдет только совпадение с каталог. Другими словами, foo/будет соответствовать каталогу foo и paths под ним, но не будет соответствовать регулярному файлу или символической ссылке foo (это согласуется с тем, как метод pathspec работает вообще в Git).

Теперь предположим, что мы имеем следующую структуру dir:

/path/to/git/repo
|-- .gitignore
|-- /cache
    |-- somefile
    |-- README    
    |-- /dir
        |-- somefile2
        |-- README

И мы хотим игнорировать все файлы внутри кеша/кроме файлов README.

Если мы укажем gitignore следующим образом:

/cache/**
!README

Git будет игнорировать все, кроме /cache/README. Другой README не будет отображаться, потому что его каталог /cache/dir был исключен с помощью /cache/**, а !README даже не применим к нему. Чтобы решить проблему, нам нужно указать gitignore следующим образом:

# Ignore everything inside cache/ dir
/cache/**
# Except for subdirectories(won't be commited anyway if there is no commited file inside)
!/cache/**/
# And except for README files
!README