Белый список и подкаталоги в Git

Я создал белый список только для текстовых файлов.

*
!*.txt

Теперь у меня есть неотслеживаемый текстовый файл в подкаталоге - sub/dir/file.txt, и он НЕ отображается (игнорируется). Однако отображаются текстовые файлы в корневом каталоге.

Почему так и как это исправить?


person Nate    schedule 06.02.2012    source источник
comment
Связано: stackoverflow.com/q/987142/78845   -  person Johnsyweb    schedule 06.02.2012
comment
Файлы, которые вы хотите включить в подкаталог? Если это так, то этот подкаталог уже может быть проигнорирован первой звездочкой в ​​вашем .gitignore.   -  person fajran    schedule 06.02.2012
comment
да. Эти файлы будут такими же низкими в структуре каталогов, как папка 11.1.102.55 в моем примере. Вложенность не всегда одинакова между папками/продуктами.   -  person Nate    schedule 06.02.2012
comment
Если вас это устраивает, .gitignore также может находиться внутри подкаталога и фильтровать все внутри этого подкаталога.   -  person fajran    schedule 06.02.2012
comment
Я знаю об этой функции. У нас есть сотни каталогов. Было бы быстрее просто явно игнорировать типы файлов, которые нам не нужны, чем создавать один gitignore для каждого каталога. Я действительно ищу способ получить функциональность белого списка из файла .gitignore.   -  person Nate    schedule 06.02.2012
comment
По сути, это дубликат того другого вопроса, но у этого есть правильный ответ...   -  person Tobias Kienzler    schedule 09.10.2012
comment
Я не понимаю, как это дубликат. Другой вопрос спрашивает, как внести в белый список определенные файлы, а этот спрашивает, как внести в белый список определенные типы файлов, включая подпапки. На самом деле это больше похоже на дубликат stackoverflow.com/questions/8024924/.   -  person Big McLargeHuge    schedule 17.04.2013
comment
@ davidkennedy85 Я отредактировал вопрос, чтобы подчеркнуть разницу, и пометил его для повторного открытия.   -  person sashoalm    schedule 03.10.2013
comment
fwiw, дедушка повторяющихся ответов по этой теме - тот, который вы должны просмотреть, - вероятно, будет Заставить .gitignore игнорировать все, кроме нескольких файлов - очень регулярная активность и несколько хороших ответов. Мне особенно нравится этот ответ, который кажется ясным и подробным.   -  person Kay V    schedule 20.07.2018


Ответы (3)


Если вы попытаетесь сделать это таким образом, это не удастся, потому что вы в конечном итоге внесете каталоги в черный список в своей структуре.

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

Файл .gitignore, который будет это делать:

# First, ignore everything
*
# Now, whitelist anything that's a directory
!*/
# And all the file types you're interested in.
!*.one
!*.two
!*.etc

Протестировал это в трехуровневой структуре белого списка для файлов .txt при наличии файлов *.one, *.two и *.three с использованием файла .gitignore, расположенного в корневом каталоге репозитория - у меня работает. Вам не нужно будет добавлять .gitignore файлов во все каталоги в вашей структуре.

Информация, которую я использовал, чтобы выяснить ответ, пришла, среди прочего, из этого (stackoverflow.com).

person simont    schedule 10.02.2012
comment
Вам также нужна запись !.gitignore при использовании *, не так ли? - person sjas; 06.08.2013
comment
Смотрите мой ответ здесь: stackoverflow.com/questions/987142/ Может быть полезнее использовать /* для добавления в черный список только папки верхнего уровня, но не рекурсивно для всех папок, что на самом деле означает, что .gitignore не следует заглядывать в подпапки папки из белого списка. - person Ryan Taylor; 21.07.2015

Более простой способ добиться этого:

# Ignore all files...
*.*

# ...except the ones we want
!*.txt

Это работает, потому что gitignore применяет шаблоны, которые не начинаются с /, к каждому уровню ниже файла .gitignore:

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

Если вы хотите сделать это с файлами внутри каталога, все становится сложнее:

# Ignore all files in all directories inside subdir...
/subdir/**/*.*

# ...except the ones we want
!/subdir/**/*.txt

Это работает, потому что gitignore имеет специальные правила для **:

Две последовательные звездочки (**) в шаблонах, совпадающих с полным путем, могут иметь особое значение:

  • Косая черта, за которой следуют две последовательные звездочки, после чего косая черта соответствует нулю или более каталогам. Например, a/**/b соответствует a/b, a/x/b, a/x/y/b и так далее.

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

person Sharadh    schedule 30.04.2020

Я долго искал:

  1. Предположим, у меня есть большая структура папок с ~ 100 000 рекурсивно вложенными каталогами. В этих папках около 30 000 файлов типа .txt (в моем случае: типа *.md). Рядом с этими *.md файлами есть, скажем, 500 ГБ (более миллиона) файлов, которые я не хочу отслеживать.

  2. Я хочу, чтобы git отслеживал только .txt (или *.md) файлов во всех папках и подкаталогах.

Правильный ответ должен быть таким: это невозможно в Git.

Что я сделал вместо этого:

[редактировать: тоже не сработало - я пытался создать папку с символическими ссылками (или жесткими ссылками) и использовать там git, но git не следует символическим ссылкам и перезаписывает жесткие ссылки. Дох!]

person Alex    schedule 21.02.2020