Какая разница между Git игнорированием каталога и каталога/*?
Я смущен тем, что правильный способ игнорировать содержимое каталога в git.
Предположим, что у меня есть следующая структура каталогов:
my_project
|--www
|--1.txt
|--2.txt
|--.gitignore
В чем разница между установкой этого:
www
И это?
www/*
Причина, по которой я задаю этот вопрос: В git, если каталог пуст, git не будет включать такой пустой каталог в репозиторий. Поэтому я пытался найти решение, которое добавляет дополнительный файл .gitkeep в каталог, чтобы он не был пустым. Когда я пытался это решение, если в файле .gitignore я пишу, как показано ниже:
www
!*.gitkeep
Это не работает (я намерен игнорировать все содержимое в разделе www, но сохранить каталог). Но если я попробую следующее:
www/*
!*.gitkeep
Тогда это сработает! Поэтому я думаю, что это должно иметь некоторые различия между двумя подходами.
Ответы
Ответ 1
Существуют различия между www
, www/
и www/*
.
В основном из документации и моих собственных тестов www
найти совпадение с файлом или каталогом www/
только соответствует каталогу, а www/*
соответствует каталогам и файлам внутри www
.
Я расскажу только о различиях между www/
и www/*
здесь, так как различия между www
и www/
очевидны.
Для www/
, git игнорирует сам каталог www
, что означает, что git даже не заглянет внутрь. Но для www/*
, git проверяет все файлы/папки внутри www
и игнорирует их все с помощью шаблона *
. Кажется, это приводит к тем же результатам, поскольку git не будет отслеживать пустую папку www
, если все ее дочерние файлы/папки игнорируются. И действительно, результаты не будут иметь разницы для случая OP с автономным значением www/
или www/*
. Но он делает различия, если он сочетается с другими правилами.
Например, что, если мы хотим включить только www/1.txt
, но игнорировать все остальные внутри www
?
Следующий .gitignore
не будет работать.
www/
!www/1.txt
Пока работает .gitignore
, почему?
www/*
!www/1.txt
Для первого, git просто игнорирует каталог www
и даже не заглянет внутрь, чтобы включить www/1.txt
снова. Первое правило исключает родительский каталог www
, но не www/1.txt
, и в результате www/1.txt
не может быть " включен снова".
Но для последнего git сначала игнорирует все файлы/файлы в www
, а затем включает один из них, который является www/1.txt
.
В этом примере следующие строки в документации могут помочь:
Дополнительный префикс "!" что отрицает шаблон; любой соответствующий файл исключенный предыдущим шаблоном, снова включается. Это не можно повторно включить файл, если родительский каталог этого файла исключены.
Ответ 2
Я просто разбираюсь в документации, и насколько я могу судить, они отличаются только более продвинутыми шаблонами, например.
$ cat .gitignore
# exclude everything except directory foo/bar
/*
!/foo
/foo/*
!/foo/bar
Я проверил выше, и если вы замените !/foo
на !/foo/*
, вы действительно получите другой результат.
Примечание
foo
Будет исключен любой файл foo
, но
foo/
будет исключать только каталоги с именем foo.
Ответ 3
Помимо совершенно хороших ответов, которые вы уже получили, вы должны заметить, что вы можете иметь .gitignore
в любом месте вашего проекта, включая подпапки.
Итак, если вы хотите игнорировать все файлы внутри www
, но хотите, чтобы папка www
была версией, вместо использования пустого .gitkeep
, .dummy
или любого другого имени, которое вы выберете, почему бы не использовать .gitignore
там, говоря игнорировать все файлы?
/
|- .gitignore (a)
\- www
|- .gitignore (b)
|- 1.jpg
\- 2.jpg
В корневом каталоге .gitignore
(a) вы ничего не скажете о папке www
или ее содержимом.
В www/.gitignore
(b) вы добавили следующее:
# ignore all files in this folder except this .gitignore
*
!.gitignore
Таким образом, все выглядит более организованным (по крайней мере, для меня).
Ответ 4
Чтобы игнорировать все в каталоге, кроме dotfiles, вы можете использовать следующий шаблон glob в своем .gitignore
:
www/[^.]*
Поэтому нет необходимости в дополнительном .gitignore
, просто добавьте файл .keep
в каталог www
.