.gitignore исключить папку, но включить определенную подпапку
965
У меня есть папка, application/которую я добавляю в .gitignore. Внутри application/папки находится папка application/language/gr. Как я могу включить эту папку?
Если вы исключите application/, то все, что находится под ним, всегда будет исключено (даже если какой-то более поздний шаблон отрицательного исключения («unignore») может совпадать с чем-то ниже application/).
Чтобы делать то, что вы хотите, вы должны «игнорировать» каждый родительский каталог всего, что вы хотите «игнорировать». Обычно вы в конечном итоге пишете правила для этой ситуации попарно: игнорируйте все в каталоге, но не какой-то определенный подкаталог.
# you can skip this first one if it is not already excluded by prior patterns
!application/
application/*
!application/language/
application/language/*
!application/language/gr/
Примечание
Трейлинг /*является значительным:
Шаблон dir/исключает каталог с именем dirи (неявно) все под ним.
С помощью dir/Git никогда не будет смотреть на что-либо ниже dir, и, таким образом, никогда не будет применять какие-либо шаблоны «неисключения» к чему-либо ниже dir.
Шаблон dir/*ничего не говорит о dirсебе; это просто исключает все под dir. С помощью dir/*Git будет обрабатывать прямое содержимое dir, давая другим шаблонам возможность «исключить» некоторую часть содержимого ( !dir/sub/).
Важны ли конечные звездочки? Если так, то в чем разница в значении? В соответствии с алгоритмом, описанным в документации gitignore , конец косой черты соответствует каталогу и путям под этим каталогом. Окончание со звездочкой тогда относилось бы к лечению как шаблон шара. Эксперимент показывает, что работает вариант звездочки, но не тот, который заканчивается только косой чертой. Я хотел бы понять, почему это так.
SEH
123
@seh: Да, отставание /*является значительным. Если каталог исключен, Git никогда не будет просматривать содержимое этого каталога. Шаблон dir/исключает каталог с именем dirи (неявно) все под ним. Шаблон dir/*ничего не говорит о dirсебе; это просто исключает все под dir. С помощью dir/Git никогда не будет смотреть на что-либо ниже dir, и, таким образом, никогда не будет применять какие-либо шаблоны «неисключения» к чему-либо ниже dir. С помощью dir/*Git будет обрабатывать прямое содержимое dir, давая другим шаблонам возможность «исключить» некоторую часть содержимого ( !dir/sub/).
Крис Джонсен
7
Ах, это объясняет это. Независимо от того, сколько раз я читал документацию gitignore , я так и не понял, когда не работают обратные шаблоны. С твоим объяснением теперь понятно. Документация gitignore нуждается в разделе «рецепт», чтобы объяснить, как это сделать.
SEH
8
Я не мог заставить это работать (безумный файл .gitignore!), Поэтому вместо этого я просто принудительно добавил файлы после cd'ing в каталог, который хотел. git add -f .
K0D4
2
Обратите внимание, что вы не можете полагаться на вывод git status, который просто скажет вам, что каталог верхнего уровня будет добавлен. Вместо этого сделайте git addкаталог верхнего уровня и затем git status(будем надеяться) перечислите подмножество файлов, которые были сопоставлены с шаблоном.
gitignore.txt: уточнить рекурсивный характер исключенных каталогов
Необязательный префикс " !", который отменяет шаблон; любой соответствующий файл, исключенный предыдущим шаблоном, снова будет включен.
Невозможно повторно включить файл, если родительский каталог этого файла исключен. ( *)
( *: если в git 2.8+ не соблюдаются определенные условия, см. ниже)
Git не выводит список исключенных каталогов по соображениям производительности, поэтому любые шаблоны для содержащихся файлов не влияют, независимо от того, где они определены.
Поставьте обратную косую черту (" \") перед первым " !" для шаблонов, начинающихся с буквального " !", например, " \!important!.txt".
Пример для исключения всего, кроме определенного каталога foo/bar(обратите внимание на то, что /*- без косой черты, подстановочный знак также будет исключать все внутри foo/bar):
Сначала вы должны занести в белый список папки , прежде чем сможете занести в белый список файлы в данной папке.
Обновление февраль / март 2016:
Обратите внимание, что в git 2.9.x / 2.10 (середина 2016 года?) Может быть возможно повторно включить файл, если родительский каталог этого файла исключен, если в пути не указан подстановочный знак .
Я пытался использовать обновленный синтаксис повторного включения, который был опубликован в конце вашего ответа на git для windows, v2.8.1.windows.1но он не работает :(
Дэвид Хэнкок,
1
@DavidHancock Извините, я отредактировал ответ: это еще не доступно.
VonC
1
@DavidHancock меня тоже: это более 13 ответов Stack Overflow, которые мне приходилось редактировать несколько раз!
VonC
5
Git 2.9 был выпущен вчера. Подтверждение шаблона application/+ !application/language/gr/, упомянутого в ответе, работает должным образом.
@Chris Johnsen ответил великолепно, но в более новых версиях Git (1.8.2 или новее) существует шаблон с двумя звездочками, который можно использовать для более краткого решения:
# assuming the root folder you want to ignore is 'application'
application/**/*
# the subfolder(s) you want to track:
!application/language/gr/
Таким образом, вам не нужно «игнорировать» родительский каталог подпапки, которую вы хотите отслеживать.
В Git 2.17.0 (Не знаю, как раньше, до этой версии. Возможно, до версии 1.8.2), работает **шаблон, объединенный с exclude для каждого подкаталога, ведущего к вашим файлам. Например:
# assuming the root folder you want to ignore is 'application'
application/**
# Explicitly track certain content nested in the 'application' folder:
!application/language/
!application/language/gr/
!application/language/gr/** # Example adding all files & folder in the 'gr' folder
!application/language/gr/SomeFile.txt # Example adding specific file in the 'gr' folder
Увы, это терпит неудачу (Git 1.8.4.msysgit.0), потому что шаблон **может соответствовать нулевым подпапкам, и *будет совпадать languageи исключать его, предотвращая включение gr. Полная цепочка родителей, которую рекомендует Крис Джонсон, кажется необходимой.
Шон Гуглер
3
Звучит отлично, но у меня это не работает в git 2.3.7 ... /www/**/* !/www/config.xml !/www/resconfig.xml, а каталог res все еще игнорируется.
Роб
@Rob вам также нужно добавить !/www/res/. Вы можете использовать folder/**/*шаблон, но вам все равно нужно добавить исключения для каждого подкаталога, который вы хотите добавить. Это все еще короче и более читабельно, чем комбинация игнорирования / исключения.
Бен Кейн
Я знаю, что это старый комментарий, но если вам интересно. Я добавил правку в ответ, документирующую этот подход.
Бен Кейн
21
Есть множество похожих вопросов по этому поводу, поэтому я выложу то, что написал ранее:
Единственный способ заставить это работать на моей машине - это сделать так:
# Ignore all directories, and all sub-directories, and it's contents:
*/*
#Now ignore all files in the current directory
#(This fails to ignore files without a ".", for example
#'file.txt' works, but
#'file' doesn't):
*.*
#Only Include these specific directories and subdirectories:
!wordpress/
!wordpress/*/
!wordpress/*/wp-content/
!wordpress/*/wp-content/themes/
!wordpress/*/wp-content/themes/*
!wordpress/*/wp-content/themes/*/*
!wordpress/*/wp-content/themes/*/*/*
!wordpress/*/wp-content/themes/*/*/*/*
!wordpress/*/wp-content/themes/*/*/*/*/*
Обратите внимание, как вы должны явно разрешить контент для каждого уровня, который вы хотите включить. Так что, если у меня есть подкаталоги 5 глубоко под темами, мне все еще нужно разобрать это.
Самый простой и, вероятно, лучший способ - попытаться добавить файлы вручную (обычно это имеет приоритет над .gitignoreправилами-стилей):
git add /path/to/module
Вы можете даже хотите -Nнамерение добавить флаг, чтобы предложить вам будет добавить их, но не сразу. Я часто делаю это для новых файлов, которые я еще не готов подготовить.
Это копия ответа, размещенного на том, что легко может быть дубликатом QA. Я размещаю его здесь для большей наглядности - мне проще не иметь беспорядка в правилах gitignore.
Спасибо за этот ответ. Мне пришлось добавить -f, так как он есть в моем .gitignore, вот так: git add -f path / to / file
jasonflaherty
6
Итак, поскольку многие программисты используют ноды. вариант использования, который отвечает этому вопросу, должен исключать, node_modulesкроме одного модуля, module-aнапример:
!/.vs/ <== include this folder to source control, folder only, nothing else
/.vs/* <== but ignore all files and sub-folder inside this folder
!/.vs/ProjectSettings.json <== but include this file to source control
!/.vs/config/ <== then include this folder to source control, folder only, nothing else
!/.vs/config/* <== then include all files inside the folder
Это был самый полезный ответ для меня, поскольку визуальные эффекты помогли. Спасибо!
Джоэл Мерфи
4
Особенно для старых версий Git большинство предложений не будут работать так хорошо. Если это так, я бы поместил отдельный каталог .gitignore в каталог, куда я хочу, чтобы контент был включен, независимо от других настроек, и разрешил там, что нужно.
Например: /.gitignore
# ignore all .dll files
*.dll
/dependency_files/.gitignore
# include everything
!*
Так что все в / dependency_files (даже .dll файлы) включены просто отлично.
Я нашел похожий случай, когда в laravel по умолчанию .gitignoreигнорирует все, используя asterix, а затем переопределяет публичный каталог.
*
!public
!.gitignore
Этого недостаточно, если вы столкнетесь с сценарием OP.
Если вы хотите зафиксировать определенные подпапки public, скажем, например, в свой public/productsкаталог, вы хотите включить файлы, которые имеют глубину в одну подпапку, например, включить, что public/products/a/b.jpgони не будут обнаружены правильно, даже если вы добавите их именно так !/public/products,!public/products/* и т. Д.
Решение состоит в том, чтобы убедиться, что вы добавляете запись для каждого уровня пути, как этот, чтобы переопределить их все.
Еще один пример перехода по структуре каталогов, чтобы получить именно то, что вы хотите. Примечание: я не исключаю, Library/ноLibrary/**/*
# .gitignore file
Library/**/*
!Library/Application Support/
!Library/Application Support/Sublime Text 3/
!Library/Application Support/Sublime Text 3/Packages/
!Library/Application Support/Sublime Text 3/Packages/User/
!Library/Application Support/Sublime Text 3/Packages/User/*macro
!Library/Application Support/Sublime Text 3/Packages/User/*snippet
!Library/Application Support/Sublime Text 3/Packages/User/*settings
!Library/Application Support/Sublime Text 3/Packages/User/*keymap
!Library/Application Support/Sublime Text 3/Packages/User/*theme
!Library/Application Support/Sublime Text 3/Packages/User/**/
!Library/Application Support/Sublime Text 3/Packages/User/**/*macro
!Library/Application Support/Sublime Text 3/Packages/User/**/*snippet
!Library/Application Support/Sublime Text 3/Packages/User/**/*settings
!Library/Application Support/Sublime Text 3/Packages/User/**/*keymap
!Library/Application Support/Sublime Text 3/Packages/User/**/*theme
> git add Library
> git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: Library/Application Support/Sublime Text 3/Packages/User/Default (OSX).sublime-keymap
new file: Library/Application Support/Sublime Text 3/Packages/User/ElixirSublime.sublime-settings
new file: Library/Application Support/Sublime Text 3/Packages/User/Package Control.sublime-settings
new file: Library/Application Support/Sublime Text 3/Packages/User/Preferences.sublime-settings
new file: Library/Application Support/Sublime Text 3/Packages/User/RESTer.sublime-settings
new file: Library/Application Support/Sublime Text 3/Packages/User/SublimeLinter/Monokai (SL).tmTheme
new file: Library/Application Support/Sublime Text 3/Packages/User/TextPastryHistory.sublime-settings
new file: Library/Application Support/Sublime Text 3/Packages/User/ZenTabs.sublime-settings
new file: Library/Application Support/Sublime Text 3/Packages/User/adrian-comment.sublime-macro
new file: Library/Application Support/Sublime Text 3/Packages/User/json-pretty-generate.sublime-snippet
new file: Library/Application Support/Sublime Text 3/Packages/User/raise-exception.sublime-snippet
new file: Library/Application Support/Sublime Text 3/Packages/User/trailing_spaces.sublime-settings
gitignore - Определяет намеренно не отслеживаемые файлы для игнорирования.
Пример, чтобы исключить все, кроме определенного каталога foo / bar (обратите внимание на / * - без косой черты подстановочный знак также исключит все, что находится внутри foo / bar ):
Я часто использую этот обходной путь в CLI, где вместо настройки моего .gitignoreя создаю отдельный .includeфайл, в котором я определяю (под) каталоги, которые я хочу включить, несмотря на каталоги, которые прямо или рекурсивно игнорируются.gitignore .
Таким образом, я дополнительно использую
git add `cat .include`
во время постановки, перед совершением.
Для OP, я предлагаю использовать, .includeкоторый имеет эти строки:
<parent_folder_path>/application/language/gr/*
ПРИМЕЧАНИЕ. Использование catне позволяет использовать псевдонимы (в пределах .include) для указания $ HOME (или любого другого конкретного каталога). Это связано с тем, что строка, homedir/app1/*
переданная с git addиспользованием вышеуказанной команды, выглядит как git add 'homedir/app1/*', а заключенные в одинарные кавычки символы ('') сохраняют буквальное значение каждого символа в кавычках, тем самым предотвращая функционирование псевдонимов (таких как homedir ) (см. Bash Single). Цитаты ).
Вот пример .includeфайла, который я использую в своем репо здесь .
.gitignore
шаблонному формату» стала более понятной (декабрь 2013 г.). Смотрите мой ответ нижеОтветы:
Если вы исключите
application/
, то все, что находится под ним, всегда будет исключено (даже если какой-то более поздний шаблон отрицательного исключения («unignore») может совпадать с чем-то нижеapplication/
).Чтобы делать то, что вы хотите, вы должны «игнорировать» каждый родительский каталог всего, что вы хотите «игнорировать». Обычно вы в конечном итоге пишете правила для этой ситуации попарно: игнорируйте все в каталоге, но не какой-то определенный подкаталог.
Примечание
Трейлинг
/*
является значительным:dir/
исключает каталог с именемdir
и (неявно) все под ним.С помощью
dir/
Git никогда не будет смотреть на что-либо нижеdir
, и, таким образом, никогда не будет применять какие-либо шаблоны «неисключения» к чему-либо нижеdir
.dir/*
ничего не говорит оdir
себе; это просто исключает все подdir
. С помощьюdir/*
Git будет обрабатывать прямое содержимоеdir
, давая другим шаблонам возможность «исключить» некоторую часть содержимого (!dir/sub/
).источник
/*
является значительным. Если каталог исключен, Git никогда не будет просматривать содержимое этого каталога. Шаблонdir/
исключает каталог с именемdir
и (неявно) все под ним. Шаблонdir/*
ничего не говорит оdir
себе; это просто исключает все подdir
. С помощьюdir/
Git никогда не будет смотреть на что-либо нижеdir
, и, таким образом, никогда не будет применять какие-либо шаблоны «неисключения» к чему-либо нижеdir
. С помощьюdir/*
Git будет обрабатывать прямое содержимоеdir
, давая другим шаблонам возможность «исключить» некоторую часть содержимого (!dir/sub/
).git add -f .
git status
, который просто скажет вам, что каталог верхнего уровня будет добавлен. Вместо этого сделайтеgit add
каталог верхнего уровня и затемgit status
(будем надеяться) перечислите подмножество файлов, которые были сопоставлены с шаблоном.Коммит 59856de от Karsten Blees (kblees) для Git 1.9 / 2.0 (первый квартал 2014 года) проясняет этот случай:
gitignore.txt
: уточнить рекурсивный характер исключенных каталоговВ твоем случае:
Сначала вы должны занести в белый список папки , прежде чем сможете занести в белый список файлы в данной папке.
Обновление февраль / март 2016:
Обратите внимание, что в git 2.9.x / 2.10 (середина 2016 года?) Может быть возможно повторно включить файл, если родительский каталог этого файла исключен, если в пути не указан подстановочный знак .
Nguyễn Thái Ngọc Duy (
pclouds
) пытается добавить эту функцию:Так что с git 2.9+ это могло бы сработать, но в конечном итоге было отменено:
источник
v2.8.1.windows.1
но он не работает :(application/
+!application/language/gr/
, упомянутого в ответе, работает должным образом.@Chris Johnsen ответил великолепно, но в более новых версиях Git (1.8.2 или новее) существует шаблон с двумя звездочками, который можно использовать для более краткого решения:
Таким образом, вам не нужно «игнорировать» родительский каталог подпапки, которую вы хотите отслеживать.
В Git 2.17.0 (Не знаю, как раньше, до этой версии. Возможно, до версии 1.8.2), работает
**
шаблон, объединенный с exclude для каждого подкаталога, ведущего к вашим файлам. Например:источник
**
может соответствовать нулевым подпапкам, и*
будет совпадатьlanguage
и исключать его, предотвращая включениеgr
. Полная цепочка родителей, которую рекомендует Крис Джонсон, кажется необходимой./www/**/* !/www/config.xml !/www/res
config.xml, а каталог res все еще игнорируется.!/www/res/
. Вы можете использоватьfolder/**/*
шаблон, но вам все равно нужно добавить исключения для каждого подкаталога, который вы хотите добавить. Это все еще короче и более читабельно, чем комбинация игнорирования / исключения.Есть множество похожих вопросов по этому поводу, поэтому я выложу то, что написал ранее:
Единственный способ заставить это работать на моей машине - это сделать так:
Обратите внимание, как вы должны явно разрешить контент для каждого уровня, который вы хотите включить. Так что, если у меня есть подкаталоги 5 глубоко под темами, мне все еще нужно разобрать это.
Это из комментария @ Ярина здесь: https://stackoverflow.com/a/5250314/1696153
Это были полезные темы:
Я тоже пробовал
а также
**/wp-content/themes/**
или
/wp-content/themes/**/*
Ничто из этого не сработало для меня. Много проб и ошибок!
источник
!
правила внизу.Я нашел только это на самом деле работает.
источник
Самый простой и, вероятно, лучший способ - попытаться добавить файлы вручную (обычно это имеет приоритет над
.gitignore
правилами-стилей):Вы можете даже хотите
-N
намерение добавить флаг, чтобы предложить вам будет добавить их, но не сразу. Я часто делаю это для новых файлов, которые я еще не готов подготовить.Это копия ответа, размещенного на том, что легко может быть дубликатом QA. Я размещаю его здесь для большей наглядности - мне проще не иметь беспорядка в правилах gitignore.
источник
Итак, поскольку многие программисты используют ноды. вариант использования, который отвечает этому вопросу, должен исключать,
node_modules
кроме одного модуля,module-a
например:источник
2.10.2.windows.1
.Добавить дополнительный ответ:
вот результат:
источник
Особенно для старых версий Git большинство предложений не будут работать так хорошо. Если это так, я бы поместил отдельный каталог .gitignore в каталог, куда я хочу, чтобы контент был включен, независимо от других настроек, и разрешил там, что нужно.
Например: /.gitignore
/dependency_files/.gitignore
Так что все в / dependency_files (даже .dll файлы) включены просто отлично.
источник
Я нашел похожий случай, когда в laravel по умолчанию
.gitignore
игнорирует все, используя asterix, а затем переопределяет публичный каталог.Этого недостаточно, если вы столкнетесь с сценарием OP.
Если вы хотите зафиксировать определенные подпапки
public
, скажем, например, в свойpublic/products
каталог, вы хотите включить файлы, которые имеют глубину в одну подпапку, например, включить, чтоpublic/products/a/b.jpg
они не будут обнаружены правильно, даже если вы добавите их именно так!/public/products
,!public/products/*
и т. Д.Решение состоит в том, чтобы убедиться, что вы добавляете запись для каждого уровня пути, как этот, чтобы переопределить их все.
источник
Еще один пример перехода по структуре каталогов, чтобы получить именно то, что вы хотите. Примечание: я не исключаю,
Library/
ноLibrary/**/*
> git add Library
> git status
источник
В WordPress это помогло мне:
источник
gitignore - Определяет намеренно не отслеживаемые файлы для игнорирования.
Пример, чтобы исключить все, кроме определенного каталога foo / bar (обратите внимание на / * - без косой черты подстановочный знак также исключит все, что находится внутри foo / bar ):
Еще один пример для WordPress :
Больше информации здесь: https://git-scm.com/docs/gitignore
источник
Я часто использую этот обходной путь в CLI, где вместо настройки моего
.gitignore
я создаю отдельный.include
файл, в котором я определяю (под) каталоги, которые я хочу включить, несмотря на каталоги, которые прямо или рекурсивно игнорируются.gitignore
.Таким образом, я дополнительно использую
во время постановки, перед совершением.
Для OP, я предлагаю использовать,
.include
который имеет эти строки:ПРИМЕЧАНИЕ. Использование
cat
не позволяет использовать псевдонимы (в пределах.include
) для указания $ HOME (или любого другого конкретного каталога). Это связано с тем, что строка,homedir/app1/*
переданная сgit add
использованием вышеуказанной команды, выглядит какgit add 'homedir/app1/*'
, а заключенные в одинарные кавычки символы ('') сохраняют буквальное значение каждого символа в кавычках, тем самым предотвращая функционирование псевдонимов (таких как homedir ) (см. Bash Single). Цитаты ).Вот пример
.include
файла, который я использую в своем репо здесь .источник
Я хотел отследить JS-файлы JQuery производства, и это сработало:
источник
моя конфигурация JetBrains IntelliJ IDEA .gitignore, где мне нужно исключить
.idea
папку wholde, кроме.idea/runConfigurations
:см .: https://github.com/daggerok/gitignore-idea-runConfigurations
источник