.gitignore исключить папку, но включить определенную подпапку

У меня есть папка application/, которую я добавляю в.gitignore. Внутри приложения / папки находится папка application/language/gr. Как я могу включить эту папку? Я пробовал это

application/
!application/language/gr/

без удачи...

21 ответ

Решение

Если вы исключите 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/).

Коммит 59856de от Karsten Blees (kblees) для Git 1.9 / 2.0 (первый квартал 2014 года) проясняет этот случай:

gitignore.txt: уточнить рекурсивный характер исключенных каталогов

Необязательный префикс " ! msgstr "который отменяет шаблон; любой соответствующий файл, исключенный предыдущим шаблоном, снова будет включен.

Невозможно повторно включить файл, если родительский каталог этого файла исключен. ( * )
( * : если в git 2.8+ не выполнены определенные условия, см. ниже)
Git не выводит список исключенных каталогов по соображениям производительности, поэтому любые шаблоны для содержащихся файлов не влияют, независимо от того, где они определены.

Поставить обратную косую черту (" \ ") перед первым" ! "для шаблонов, которые начинаются с буквального" ! ", например, " \!important!.txt ".

Пример для исключения всего, кроме определенного каталога foo/bar (Обратите внимание /* - без косой черты подстановочный знак также исключает все, что находится внутри foo/bar):

 --------------------------------------------------------------
     $ cat .gitignore
     # exclude everything except directory foo/bar
     /*
     !/foo
     /foo/*
     !/foo/bar
 --------------------------------------------------------------

В твоем случае:

application/*
!application/**/
!application/language/gr/**

Сначала вы должны занести в белый список папки, прежде чем сможете занести в белый список файлы в данной папке.


Обновление февраль / март 2016:

Обратите внимание, что в git 2.9.x/2.10 (середина 2016 года?) Может оказаться возможным повторно включить файл, если родительский каталог этого файла будет исключен, если в пути не будет подстановочного знака.

Nguy Thn Thái Ngọc Duy ( pclouds ) пытается добавить эту функцию:

Так что с 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), используя ** шаблон в сочетании с исключениями для каждого подкаталога, ведущего к вашим файлам работает. Например:

# 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

Я нашел только это на самом деле работает.

**/node_modules/*
!**/node_modules/keep-dir

По этому поводу есть куча похожих вопросов, поэтому я выложу то, что написал ранее:

Единственный способ заставить это работать на моей машине - это сделать так:

# 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 глубоко под темами, мне все еще нужно разобрать это.

Это из комментария @ Ярина здесь: /questions/27976168/ispolzovaniegitignore-dlya-ignorirovaniya-vsego-krome-opredelennyih-katalogov/27976178#27976178

Это были полезные темы:

Я тоже пробовал

*
*/*
**/**

а также **/wp-content/themes/**

или же /wp-content/themes/**/*

Ничто из этого не сработало для меня. Много следов и ошибок!

Самый простой и, вероятно, лучший способ - попробовать добавить файлы вручную (обычно это имеет приоритет перед .gitignoreправила стиля):

git add /path/to/module

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


Это копия ответа, размещенного на том, что легко может быть дубликатом QA. Я публикую его здесь для большей наглядности - мне легче не иметь беспорядка правил gitignore.

Я хотел отслеживать файлы конфигурации Nagios, расположенные в /etc/nagios/ вместе с плагинами в /usr/lib64/nagios/plugins/. Для этого я инициализировал репозиторий git в / и использовал следующий список исключений:

      /*
!etc
etc/*
!etc/nagios
!usr
usr/*
!usr/lib64
usr/lib64/*
!usr/lib64/nagios
usr/lib64/nagios/*
!usr/lib64/nagios/plugins

Git проходит по списку вот так:

      /*             exclude everything under / ...
!etc           but include /etc back
etc/*             exclude everything under /etc/...
!etc/nagios       but include /etc/nagios back
!usr           but include /usr back
usr/*             exclude everything under /usr/...
                  and so on...

add a file named .gitignore to subfolder, then fill with

      !/Bin/

this works for me!

Я нашел похожий случай здесь, где в Laravel по умолчанию, .gitignore игнорирует все, используя asterix, затем переопределяет общедоступный каталог.

*
!public
!.gitignore

Этого недостаточно, если вы столкнетесь с сценарием OP.

Если вы хотите зафиксировать определенные подпапки publicскажем, например, в вашем public/products каталог, который вы хотите включить файлы, которые находятся в одной подпапке, например, чтобы включить public/products/a/b.jpg они не будут обнаружены правильно, даже если вы добавите их именно так !/public/products, !public/products/*, так далее..

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

*
!.gitignore
!public/
!public/*/
!public/products/
!public/products/*
!public/products/*/
!public/products/*/
!public/products/*/*

Моя конфигурация JetBrains IntelliJ IDEA .gitignore, где мне нужно исключить все .idea папка кроме .idea/runConfigurations:

.idea
!.idea/
.idea/*
!.idea/runConfigurations/

см. https://github.com/daggerok/gitignore-idea-runConfigurations

gitignore - Определяет намеренно не отслеживаемые файлы для игнорирования.

Пример, чтобы исключить все, кроме определенной директории foo / bar (обратите внимание на / * - без косой черты подстановочный знак также исключит все, что находится внутри foo / bar):

$ cat .gitignore
# exclude everything except directory foo/bar
/*
!/foo
/foo/*
!/foo/bar

Еще один пример для WordPress:

!/wp-content
wp-content/*
!/wp-content/plugins
wp-content/plugins/*
!wp-content/plugins/my-awesome-plugin

Больше информации здесь: https://git-scm.com/docs/gitignore

Добавить дополнительный ответ:

!/.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

вот результат:

Итак, поскольку многие программисты используют ноды. случай использования, который отвечает этому вопросу, должен исключить node_modules кроме одного модуля module-a например:

!node_modules/

node_modules/*
!node_modules/module-a/

Это сработало для меня:

**/.idea/**
!**/.idea/copyright/
!.idea/copyright/profiles_settings.xml
!.idea/copyright/Copyright.xml

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

Например: /.gitignore

# ignore all .dll files
*.dll

/dependency_files/.gitignore

# include everything
!*

Так что все в /dependency_files (даже.dll-файлы) включены просто отлично.

В WordPress это помогло мне:

wp-admin/
wp-includes/
/wp-content/*
!wp-content/plugins/
/wp-content/plugins/*
!/wp-content/plugins/plugin-name/
!/wp-content/plugins/plugin-name/*.*
!/wp-content/plugins/plugin-name/**

Еще один пример перехода по структуре каталогов, чтобы получить именно то, что вы хотите. Примечание: я не исключил 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

Подобно этому комментарию, ни одно из решений и шаблонов не сработало для меня; заставить git добавить файлы и папки, которые следует исключить, сработало:

git add -f .

Я хотел отследить JS-файлы JQuery производства, и это сработало:

node_modules/*
!node_modules/jquery
node_modules/jquery/*
!node_modules/jquery/dist/*

Я часто использую этот обходной путь в CLI, где вместо настройки моего .gitignore Я создаю отдельный .include файл, в котором я определяю (под) каталоги, которые я хочу включить, несмотря на то, что каталоги прямо или рекурсивно игнорируются .gitignore,

Таким образом, я дополнительно использую

git add `cat .include`

во время постановки, перед совершением.

Для ФП я предлагаю использовать .include который имеет эти строки:

<parent_folder_path>/application/language/gr/*

ПРИМЕЧАНИЕ. Использование cat не позволяет использовать псевдонимы (в пределах .include) для указания $HOME (или любого другого конкретного каталога). Это потому что линия homedir/app1/* когда прошло git add использование приведенной выше команды выглядит как git add 'homedir/app1/*' и включение символов в одинарные кавычки ('') сохраняет буквальное значение каждого символа в кавычках, тем самым предотвращая функционирование псевдонимов (таких как homedir) (см. Bash Single Quotes).

Вот пример .include файл, который я использую в моем репо здесь.

/home/abhirup/token.txt
/home/abhirup/.include
/home/abhirup/.vim/*
/home/abhirup/.viminfo
/home/abhirup/.bashrc
/home/abhirup/.vimrc
/home/abhirup/.condarc

Эта проблема:

  • Вы хотите исключить application папка.
  • Вы хотите включить application/language/gr/ папка.

Решение:

Решение

Пояснение: что происходит?

  • application/ просто исключит папку приложения и все, что под ней.
  • application/* (но на этот раз с завершающей звездочкой *) исключит папку приложения, но на этот раз позволит вам повторно включить дочерний файл и каталоги.

Если вы хотите повторно включить файлы / каталоги, то:

  • Использовать ! идентифицировать файлы / каталоги, которые вы хотите повторно включить.

!application/language/gr/

Ключевые выносы

parent-folder-to-exclude/*

!parent-folder-to-exclude/child-folder-to-include/

(Надеюсь, вышеизложенное будет очень, очень понятно и просто для вас - если есть какие-либо вопросы, просто оставьте комментарий, и я постараюсь уточнить.)

Другие вопросы по тегам