gitignore: игнорировать все файлы в иерархии папок, кроме одного определенного типа файла
Я хотел бы игнорировать все файлы ниже и в папке, кроме определенного типа файла, который может быть где-то в иерархии папок:
пример
/Test
/Test/unknown/folder/structure/below
Теперь я хотел бы игнорировать все файлы в и под 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
Какие-либо предложения?
3 ответа
Я смог заставить ваш пример работать, поставив .gitignore
файл в Test/
каталог со следующим содержанием.
*
!*/
!.gitignore
!layout.css
Довольно старый вопрос, но так как я боролся с этим вопросом, даже сейчас я решил, что поделюсь фактическим решением проблемы.
Дело в том, что пока вы не можете зафиксировать пустые каталоги в Git, как если бы они были проигнорированы, это правило не относится к .gitignore
,
С https://git-scm.com/docs/gitignore
Трейлинг "/**" соответствует всему внутри. Например, "abc/**" сопоставляет все файлы в каталоге "abc" относительно расположения файла.gitignore с бесконечной глубиной.
Косая черта, за которой следуют две последовательные звездочки, затем косая черта соответствует нулю или нескольким каталогам. Например, "a/**/b" соответствует "a/b", "a/x/b", "a/x/y/b" и так далее.
** Соответствует всему внутри - буквально все - файлы и каталоги.
Это приводит нас к другому моменту в gitignore docs:
Необязательный префикс "!" который отрицает образец; любой соответствующий файл, исключенный предыдущим шаблоном, снова будет включен. Невозможно повторно включить файл, если родительский каталог этого файла исключен. Git не выводит список исключенных каталогов по соображениям производительности, поэтому любые шаблоны для содержащихся файлов не влияют, независимо от того, где они определены. Поставьте обратную косую черту ("\") перед первым "!" для шаблонов, которые начинаются с литерала "!", например, "! Important!.txt".
Если шаблон заканчивается косой чертой, он удаляется с целью следующего описания, но он будет только находить совпадение с каталогом. Другими словами, foo / будет соответствовать каталогу foo и путям под ним, но не будет совпадать с обычным файлом или символической ссылкой 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
Чтобы выполнить то, что вы хотите, вам нужно использовать некоторые отрицательные исключения.
Основная идея заключается в том, что вам нужно исключить каждый родительский каталог из любого файла, который вы хотите игнорировать.
Итак, если вы хотите, чтобы /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