Заставьте .gitignore игнорировать все, кроме нескольких файлов

1704

Я понимаю, что файл .gitignore скрывает указанные файлы из системы управления версиями Git. У меня есть проект (LaTeX), который генерирует много дополнительных файлов (.auth, .dvi, .pdf, журналы и т. Д.) Во время работы, но я не хочу, чтобы они отслеживались.

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

Тем не менее, есть ли способ сохранить выходные файлы в корне дерева проекта и использовать .gitignore, чтобы игнорировать все, кроме файлов, которые я отслеживаю с помощью Git? Что-то вроде

# Ignore everything
*

# But not these files...
script.pl
template.latex
# etc...
Эндрю
источник
12
Дубликат stackoverflow.com/q/9162919/321973 (я знаю, что это новее, но ответ там более правильный). На самом деле этот ответ , вероятно, лучший
Тобиас Кинцлер

Ответы:

2446

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

# Ignore everything
*

# But not these files...
!.gitignore
!script.pl
!template.latex
# etc...

# ...even if they are in subdirectories
!*/

# if the files to be tracked are in subdirectories
!*/a/b/file1.txt
!*/a/b/c/*
Йоаким Элофссон
источник
14
Похоже, это также «игнорирует» подпапки, так что любые файлы с именем «script.pl» в любом другом месте, кроме корневого каталога, в любом случае не будут найдены. Я использую это сейчас (с * .pl), и все файлы * .pl игнорируются, хотя их много в подкаталогах ниже файла
.gitignore
38
@PandaWood Эта проблема была поднята здесь (stackoverflow.com). Это вызвано тем, что первое выражение соответствует всему, включая каталоги, которое вы никогда не отрицаете. Чтобы исправить, добавьте (! * /), Который соответствует любым подкаталогам (рекурсивно) в текущем каталоге. Это не поможет родительскому ответу, а именно внесению в белый список определенных файлов (если они находятся в подкаталогах, вы, вероятно, захотите вручную указать полный путь или использовать специфичные для каталога файлы .gitignore).
Simont
40
Я не мог заставить это работать. Я игнорирую папку (например wp/), но я не хочу игнорировать некоторые файлы глубоко в этой папке (например wp/path/to/some/location/*). Единственный способ заставить его работать, это сделатьgit add -f wp/path/to/some/location/*
trusktr
13
@trusktr Используйте !*/исключение Симонта
Тобиас Кинцлер
7
Черт возьми, это последнее правило: !*/вся разница в моих тщетных попытках заставить .gitignoreфайл работать. Большое спасибо.
racl101
631

Если вы хотите игнорировать все содержимое каталога, кроме одного файла внутри него, вы можете написать пару правил для каждого каталога в пути к файлу. Например .gitignore, чтобы игнорировать папку pippo, кроме как в pippo / pluto / paperino.xml

.gitignore

pippo/*
!pippo/pluto
pippo/pluto/*
!pippo/pluto/paperino.xml
Джузеппе Галано
источник
58
Отличный ответ, но стоит заметить, что кто-нибудь сталкивался с этим позже, fooи foo/*это не одно и то же. Чтобы это работало, вам нужно использовать foo/*для базовой папки
thislooksfun
21
@Mayank Pippo по-итальянски тупой, а Paperino - по имени Дональд Дак, а Плутон такой же, как и по-английски. Раньше они были очень распространенной тройкой имен переменных для программирования примеров. Было приятно прочитать их снова .. :)
Гиделло
То, что говорит @thislooksfun, важно, если вы хотите «исключить папку, кроме файла x».
Чехнология
8
у меня не работает: node_modules / *! node_modules / bootstrap
SuperUberDuper
1
@simple_human Это было бы верно, если бы он игнорировал все в корне хранилища, или если у него был файл .gitignore, о котором нужно заботиться, внутри упомянутых каталогов.
xZero
245

Вы хотите использовать /*вместо *или */в большинстве случаев

Использование *допустимо, но работает рекурсивно. Это не будет смотреть на каталоги с тех пор. Люди рекомендуют !*/снова использовать белые каталоги, но на самом деле лучше поместить в черный список папку с/*

# Blacklist files/folders in same directory as the .gitignore file
/*

# Whitelist some files
!.gitignore
!README.md

# Ignore all files named .DS_Store or ending with .log
**/.DS_Store
**.log

# Whitelist folder/a/b1/ and folder/a/b2/
# trailing "/" is optional for folders, may match file though.
# "/" is NOT optional when followed by a *
!folder/
folder/*
!folder/a/
folder/a/*
!folder/a/b1/
!folder/a/b2/
!folder/a/file.txt

# Adding to the above, this also works...
!/folder/a/deeply
/folder/a/deeply/*
!/folder/a/deeply/nested
/folder/a/deeply/nested/*
!/folder/a/deeply/nested/subfolder

Приведенный выше код будет игнорировать все файлы , за исключением .gitignore, README.md, folder/a/file.txt, folder/a/b1/и folder/a/b2/и все , содержащимся в этих последних двух папках. (А .DS_Storeи *.logфайлы будут игнорироваться в этих папках.)

Очевидно, я мог бы сделать, например, !/folderили !/.gitignoreтоже.

Более подробная информация: http://git-scm.com/docs/gitignore

Райан Тейлор
источник
3
Очень умно, спасибо. ИМО, это лучший способ сделать это для сайтов WordPress с минимальным количеством правил включения. Кроме того, любые новые плагины, темы или обновления WP не удаляются и не добавляются без вашего явного разрешения. При использовании GitHub Desktop я обнаружил, что .DS_Storeфайлы не игнорируются, но через командную строку это не проблема. Чтобы обойти это, я должен был перейти **/.DS_Storeниже всех других правил.
Джибран
7
Моя внутренняя подсветка синтаксиса странно реагирует на заголовок вашего поста.
itadok
3
Gracias! Вы также можете добавить в белый список файл в папке ..! /some/folder/file.txt
PodTech.io
Круто, использование / * вместо * решило все мои проблемы, когда ответы выше не сделали. Теперь мой единственный вопрос: в чем разница между! / Folder и! / Folder / *? Если я использую папку! / Без *, она, насколько я могу судить, получает изменения для всех файлов в папке.
Даллин
1
@ Даллин нет разницы. Один белый список папок, а другой белый список детей этой папки, что делает то же самое. Единственная проблема заключается в том, что родительский файл или папка должны быть внесены в белый список, прежде чем он может быть внесен в белый список, поэтому вы не можете сделать /*то же самое !/nested/folder/*(или эквивалент !/nested/folder), не делая !/nested/или !/nestedсначала! (и, вероятно, /nested/*между). Трюк, который нужно запомнить: если вы вносите в белый список глубоко вложенную подпапку, вам необходимо полностью зачеркнуть детей в каждой подпапке, и эти черные списки будут заканчиваться «звездочкой-
Райан Тейлор
75

Немного конкретнее:

Пример: игнорировать все в webroot/cache- но сохранить webroot/cache/.htaccess.

Обратите внимание на косую черту (/) после cacheпапки:

FAILS

webroot/cache*
!webroot/cache/.htaccess

РАБОТАЕТ

webroot/cache/*
!webroot/cache/.htaccess
Nik
источник
Если вы используете VS Code, будьте осторожны, чтобы не неправильно прочитать раскраску файла после применения этого к папке с .gitkeep, потому что имя папки станет зеленым, а файл .gitkeep станет серым, как и все остальные игнорируемые файлы; .gitkeep будет выглядеть так, как будто его игнорируют, но вы должны увидеть, что справа есть
буква
55
# ignore these
*
# except foo
!foo
Сувеш Пратапа
источник
28

Чтобы игнорировать некоторые файлы в каталоге, вы должны сделать это в правильном порядке :

Например, игнорируйте все в папке «application», кроме index.php и в папке «config», обратите внимание на порядок .

Вы должны отрицать, что хотите сначала.

FAILS

application/*

!application/config/*

!application/index.php

РАБОТАЕТ

!application/config/*

!application/index.php

application/*

slatunje
источник
39
Неправильно. Вы отрицаете после «игнорировать все».
Карлос
2
Не git status.gitignore
дайте себя
10
Если git statusне собираюсь рассказывать вам, на что он смотрит и что игнорируется, то как вы можете узнать, работает ли это?
Крис
1
@kris Сначала очистите кеш git. Сначала выполните «git rm --cached *», затем вы можете выполнить «git add --all», а затем «git status» покажет вам все новые изменения gitignore.
Марк Маккоркл
20

Вы можете использовать git config status.showUntrackedFiles noи все неотслеживаемые файлы будут скрыты от вас. Смотрите man git-configподробности.

Роберт Мунтяну
источник
Это замечательно, если вы хотите зафиксировать только несколько файлов из многих!
Джош М.
16

Чтобы исключить папку из .gitignore, можно сделать следующее.

!app/

app/*
!app/bower_components/

app/bower_components/*
!app/bower_components/highcharts/

Это будет игнорировать все файлы / подпапки внутри, bower_componentsкроме /highcharts.

Парень баскин
источник
14

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

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

# 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 and files if you wish:
!wordpress/somefile.jpg
!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 глубоко под темами, мне все еще нужно разобрать это.

Это из комментария @ Ярина здесь: https://stackoverflow.com/a/5250314/1696153

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

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

*
*/*
**/**

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

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

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

Кэти
источник
2
Это единственный метод, который работает исключительно для включения определенных расширений файлов. Еще лучше, это делает великое искусство ASCII: gist.github.com/Wolfgange3311999/91c671f5e4d3c56cf5a1
Мэттью Д. Шолфилд,
10

У меня была проблема с подпапкой.

Не работает:

/custom/*
!/custom/config/foo.yml.dist

Работает:

/custom/config/*
!/custom/config/foo.yml.dist
Фабиан Пиконе
источник
9

Я перепробовал все ответы, приведенные выше, но у меня не получилось. Прочитав документацию gitignore ( здесь ), я обнаружил, что если вы сначала исключите папку, то имена файлов в подпапке не будут проиндексированы. Поэтому, если впоследствии вы используете восклицательный знак для включения файла, он не будет найден в индексе и, следовательно, не будет включен в ваш git-клиент.

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

Рабочая .gitignore:

# Ignore the 'Pro' folder, except for the '3rdparty' subfolder 
/Pro/*
!Pro/3rdparty/

# Ignore the '3rdparty' folder, except for the 'domain' subfolder
/Pro/3rdparty/*
!Pro/3rdparty/domain/

# Ignore the 'domain' folder, except for the 'modulename' subfolder
Pro/3rdparty/domain/*
!Pro/3rdparty/domain/modulename/

В результате я вижу в своем git-клиенте, что только два файла в папке Pro / 3rdparty / domain / modulename / готовятся к следующему коммиту, и это именно то, что я искал.

А если вам нужно внести в белый список несколько подпапок одной и той же папки, сгруппируйте строки восклицательного знака под оператором exclude следующим образом:

# Ignore the 'Pro' folder, except for the '3rdparty' subfolder 
/Pro/*
!Pro/3rdparty/

# Ignore the '3rdparty' folder, except for the 'domain' & 'hosting' subfolders
/Pro/3rdparty/*
!Pro/3rdparty/domain/
!Pro/3rdparty/hosting/

# Ignore the 'domain' folder, except for the 'modulename' subfolder
Pro/3rdparty/domain/*
!Pro/3rdparty/domain/modulename/

# Ignore the 'hosting' folder, except for the 'modulename' subfolder
Pro/3rdparty/hosting/*
!Pro/3rdparty/hosting/modulename/

Иначе это не будет работать как ожидалось.

Тим Б.
источник
Наконец ответ, который работал. Интересно, когда я пойму, как на самом деле работает .gitignore
Дэвид
8

Вот что сработало для меня, я хотел добавить в репозиторий только один плагин Cordova:

...
plugins/*
!plugins/cordova-plugin-app-customization
Дмитрий Сокуренко
источник
8

Я знаю, что опаздываю на вечеринку, но вот мой ответ.

Как сказал @Joakim, чтобы игнорировать файл, вы можете использовать что-то вроде ниже.

# Ignore everything
*

# But not these files...
!.gitignore
!someFile.txt

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

Например, если мы хотим пропустить все файлы в gitпроекте, но не в том, в a.txtкотором он находится aDir/anotherDir/someOtherDir/aDir/bDir/cDir. Тогда наши .gitignoreбудут примерно такими

# Skip all files
*

# But not `aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt`
!aDir/
aDir/*
!aDir/anotherDir/
aDir/anotherDir/*
!aDir/anotherDir/someOtherDir/
aDir/anotherDir/someOtherDir/*
!aDir/anotherDir/someOtherDir/aDir/
aDir/anotherDir/someOtherDir/aDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/
aDir/anotherDir/someOtherDir/aDir/bDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/
aDir/anotherDir/someOtherDir/aDir/bDir/cDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt

Приведенный выше .gitignoreфайл пропустит все каталоги и файлы, кроме!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt

Как вы могли заметить, эти правила сложно определить.

Чтобы решить эту проблему, я создал простое консольное приложение под названием git-do-not-ignore, которое сгенерирует правила для вас. Я разместил проект в github с подробной инструкцией.

Пример использования

java -jar git-do-not-ignore.jar "aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt"

Вывод

!aDir/
aDir/*
!aDir/anotherDir/
aDir/anotherDir/*
!aDir/anotherDir/someOtherDir/
aDir/anotherDir/someOtherDir/*
!aDir/anotherDir/someOtherDir/aDir/
aDir/anotherDir/someOtherDir/aDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/
aDir/anotherDir/someOtherDir/aDir/bDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/
aDir/anotherDir/someOtherDir/aDir/bDir/cDir/*
!aDir/anotherDir/someOtherDir/aDir/bDir/cDir/a.txt

Там также простой веб - версия доступна здесь

Спасибо.

theapache64
источник
7

У меня есть Jquery и Angular от беседки. Бауэр установил их в

/public_html/bower_components/jquery/dist/bunch-of-jquery-files
/public_html/bower_components/jquery/src/bunch-of-jquery-source-files
/public_html/bower_components/angular/angular-files

Минимизированный jquery находится внутри distкаталога, а angular находится внутри angularкаталога. Мне нужно было только свернутые файлы для передачи на github. Некоторое вмешательство в .gitignore, и это то, что мне удалось наколдовать ...

/public_html/bower_components/jquery/*
!public_html/bower_components/jquery/dist
/public_html/bower_components/jquery/dist/*
!public_html/bower_components/jquery/dist/jquery.min.js
/public_html/bower_components/angular/*
!public_html/bower_components/angular/angular.min.js

Надеюсь, кто-то может найти это полезным.

Марио Легенда
источник
7

Вот как я это сделал:

# Ignore everything
*

# Whitelist anything that's a directory
!*/

# Whitelist some files
!.gitignore

# Whitelist this folder and everything inside of it
!wordpress/wp-content/themes/my-theme/**

# Ignore this folder inside that folder
wordpress/wp-content/themes/my-theme/node_modules

# Ignore this file recursively
**/.DS_Store

Используйте gig status -uдля рекурсивного просмотра отдельных файлов в неотслеживаемых каталогах - git statusвы увидите только папки, которые могут заставить вас думать, что все внутри них отслежено

ЗОК
источник
5

Простое решение, если вам нужно игнорировать все, кроме нескольких файлов и нескольких корневых папок:

/*
!.gitignore
!showMe.txt
!my_visible_dir

Магия в том, что /*(как описано выше) игнорирует все в (корневой) папке, но НЕ рекурсивно.

d.raev
источник
4

У меня также были некоторые проблемы с отрицанием отдельных файлов. Я смог их зафиксировать, но моя IDE (IntelliJ) всегда жаловалась на игнорируемые файлы, которые отслеживаются.

git ls-files -i --exclude-from .gitignore

Отображены два файла, которые я исключил таким образом:

public/
!public/typo3conf/LocalConfiguration.php
!public/typo3conf/PackageStates.php

В конце концов, это сработало для меня:

public/*
!public/typo3conf/
public/typo3conf/*
!public/typo3conf/LocalConfiguration.php
!public/typo3conf/PackageStates.php

Ключ был отрицанием папки в typo3conf/ первую очередь.

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

Папка !public/typo3conf/и содержимое папки public/typo3conf/*- это две разные вещи для .gitignore.

Отличная тема! Эта проблема беспокоила меня некоторое время;)

Armin
источник
3

Пока у меня ничего не получалось, потому что я пытался добавить одну банку из lib.

Это не сработало:

build/*
!build/libs/*
!build/libs/
!build/libs/myjarfile.jar 

Это сработало:

build/*
!build/libs
Маниш Бансал
источник
3

Я получил это работает

# Vendor
/vendor/braintree/braintree_php/*
!/vendor/braintree/braintree_php/lib
raftaar1191
источник
2

Имел такую ​​же проблему, как ОП, но ни один из 10 лучших ответов не сработал .
Я наконец узнал следующее

Неверный синтаксис:

*
!bin/script.sh

Правильный синтаксис:

*
!bin
!bin/script.sh

Пояснение со страницы руководства gitignore :

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

Расширенный пример:

$ дерево.

.
├── .gitignore
└── bin
    ├── ignore.txt
    └── sub
        └── folder
            └── path
                ├── other.sh
                └── script.sh

$ cat .gitignore

*
!.gitignore
!bin
!bin/sub
!bin/sub/folder
!bin/sub/folder/path
!bin/sub/folder/path/script.sh

$ git status --untracked-files --ignored

On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .gitignore
        bin/sub/folder/path/script.sh

Ignored files:
  (use "git add -f <file>..." to include in what will be committed)
        bin/ignore.txt
        bin/sub/folder/path/other.sh

nothing added to commit but untracked files present (use "git add" to track)
frntn
источник
1

Суть

# Ignore everything
*

# But not these files...
!script.pl
!template.latex

И, вероятно, включают в себя:

!.gitignore

Ссылка

С https://git-scm.com/docs/gitignore :

Необязательный префикс " !", который отменяет шаблон; любой соответствующий файл, исключенный предыдущим шаблоном, снова будет включен. Невозможно повторно включить файл, если родительский каталог этого файла исключен. Git не выводит список исключенных каталогов по соображениям производительности, поэтому любые шаблоны в содержащихся файлах не влияют, независимо от того, где они определены. Поставьте обратную косую черту (" \") перед первым " !" для шаблонов, начинающихся с буквального " !", например, " \!important!.txt".

...

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

$ cat .gitignore
# exclude everything except directory foo/bar
/*
!/foo
/foo/*
!/foo/bar
Уилл Каин
источник
0

Кажется, я нашел то, что сработало для меня, о чем никто не упомянул.

# Ignore everything
*

# But not these files...
!.gitignore
!script.pl
!template.latex
# etc...

# And if you want to include a sub-directory and all sub-directory and files under it, but not all sub-directories
!subdir/
!subdir/**/*

По сути, это, кажется, сводит на нет подкаталог от игнорирования, вам нужно иметь две записи, одну для самого подкаталога, !subdir/а затем другую, которая распространяется на все файлы и папки в нем.!subdir/**/*

Дидье А.
источник