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

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

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

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

# Ignore everything
*

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

32 ответа

Решение

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

# 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/*

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

.gitignore

pippo/*
!pippo/pluto
pippo/pluto/*
!pippo/pluto/paperino.xml

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

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

# 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

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

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

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

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

Пример: игнорировать все в webroot/cache - но продолжай webroot/cache/.htaccess,

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

FAILS

webroot/cache*
!webroot/cache/.htaccess

РАБОТАЕТ

webroot/cache/*
!webroot/cache/.htaccess

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

Как сказал @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

Здесь также доступна простая веб-версия

Спасибо.

# ignore these
*
# except foo
!foo

Была проблема, аналогичная OP, но ни один из 10 лучших ответов на самом деле не работал.
Я наконец узнал следующее

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

*
!bin/script.sh

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

*
!bin
!bin/script.sh

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

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

Это означает, что приведенный выше "Неверный синтаксис" неверен, потому что bin/script.sh не может быть повторно включен как bin/игнорируется. Вот и все.

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

$ tree.

.
├── .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)

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

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

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

FAILS

application/*

!application/config/*

!application/index.php

РАБОТАЕТ

!application/config/*

!application/index.php

application/*

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

Так я сохраняю структуру папок, игнорируя все остальное. У вас должен быть файл README.md в каждом каталоге (или .gitkeep).

      /data/*
!/data/README.md

!/data/input/
/data/input/*
!/data/input/README.md

!/data/output/
/data/output/*
!/data/output/README.md

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

!app/

app/*
!app/bower_components/

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

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

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

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

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

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

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

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

*
*/*
**/**

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

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

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

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

# 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 вы увидите только папки, которые могут обмануть вас, если вы подумаете, что все внутри них отслеживается

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

Однако я понял, что папка, которая игнорировалась, не имеет пути. Мой .gitignore выглядел так:

      /folder/
!/folder/subfolder

Подпапка по-прежнему игнорировалась, но добавление*после того, как папка заставила его работать так

      /folder/*
!/folder/subfolder

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

Не работает:

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

Работает:

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

Я перепробовал все ответы, приведенные выше, но у меня не получилось. Прочитав документацию 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/

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

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

      # ignore all files that have an extension
**/*.*

# except for these extensions
!**/*.extension1
!**/*.extension2

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

      **/EXTENSIONLESSFILETOIGNORE

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

...
plugins/*
!plugins/cordova-plugin-app-customization

Самый простой способ сделать это - принудительно добавить файл. Он будет учтен в git, даже если он похоронен или вложен в дерево подкаталогов, игнорируемое git.

Например:

Папка x64 исключена в.gitignore:

x64/

Но вы хотите включить файл myFile.py находится в x64/Release/каталог. Тогда вам необходимо:

git add -f x64/Release/myFile.py

Вы можете сделать это для нескольких файлов файлов, которые соответствуют шаблону, например

git add -f x64/Release/myFile*.py

и так далее.

У меня есть 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 каталог. Мне нужно было только свернутые файлы для передачи на 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

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

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

/*
!.gitignore
!showMe.txt
!my_visible_dir

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

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

# Vendor
/vendor/braintree/braintree_php/*
!/vendor/braintree/braintree_php/lib

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

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

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

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

build/*
!build/libs

У меня также были некоторые проблемы с отрицанием отдельных файлов. Я смог их зафиксировать, но моя 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.

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

Это катастрофа, что после 16 лет (2005) использования git, нет простого и очевидного способа исключить один файл, расположенный глубоко в иерархии каталогов, который в противном случае следует игнорировать. Вместо этого нам нужно прибегать к безумным вещам, таким как многократное копание в структуре и исключение и включение каталогов в правильном порядке. Чего-то чертовски невозможного запомнить те 4 раза в год, которые нужно делать.

Единственная умная, но очень странная альтернатива — использовать git add --force. Что-то, что обязательно потерпит неудачу в какой-то момент, когда вы не работаете только с gitted репо.

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

      f=0; y='';for x in $(echo "uploads/rubbish/stuff/KEEP_ME/a.py" | tr '\/' '\n'); do y="$y/$x"; if [ $(($f)) -eq 0 ]; then y="$x"; f=1; fi; echo -e '!'"$y/\n$y/*"; done | sed '$d' |sed -z 's/..$//'; echo;

# output:
!uploads/
uploads/*
!uploads/rubbish/
uploads/rubbish/*
!uploads/rubbish/stuff/
uploads/rubbish/stuff/*
!uploads/rubbish/stuff/KEEP_ME/
uploads/rubbish/stuff/KEEP_ME/*
!uploads/rubbish/stuff/KEEP_ME/a.py

Описание

  • Существует оператор для корректировки 1-го элемента, не получающего .
  • tr '\/' '\n'- перевести /к \nв стандартных путях POSIX (чтобы получить список)
  • y="$y/$x"- добавить следующий подкаталог (в списке) после предыдущего каталога .
  • echo -e '!'"$y/\n$y/*"-
    напечатать 2 строки элемента подкаталога, 1-я с ! префикс и 2-й с постфиксом .
  • sed '$d'- удалить последнюю строку
  • sed -z 's/..$//'- удалить последние 2 символа /*с последней строки

Затем мы создаем функцию:

      function gitkeep () { f=0; y='';for x in $(echo "$1" | tr '\/' '\n'); do y="$y/$x"; if [[ f -eq 0 ]]; then y="$x"; f=1; fi; echo -e '!'"$y/\n$y/*"; done | sed '$d' |sed -z 's/..$//'; echo; }

# gitkeep "uploads/rubbish/stuff/KEEP_ME/a"

!uploads/
uploads/*
!uploads/rubbish/
uploads/rubbish/*
!uploads/rubbish/stuff/
uploads/rubbish/stuff/*
!uploads/rubbish/stuff/KEEP_ME/
uploads/rubbish/stuff/KEEP_ME/*
!uploads/rubbish/stuff/KEEP_ME/a

Здесь я упростил арифметику ifзаявление if [[ f -eq 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/**/*

Суть

# 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

Через github.com/gitinclude вы можете загрузить инструмент командной строки (для Windows, Linux и OSX) для включения глубоко вложенных наборов файлов.

Определите наборы файлов в .gitincludeи запустите инструмент (с помощью двойного щелчка или командной строки). Ваш .gitignoreтеперь обновляется.

Далее в структуре каталогов используйте отдельный .gitignore.

      root
|- subdirA
   |- subdirA1
      |- file1.txt
      |- file2.txt
      |- README.md
      |- .gitignore

Используйте .gitignore в корне, но тогда в root/subdirA/subdirA1 это будет содержимое .gitignore.

      *
!README.md

Надеюсь, это поможет!

Содержимое файла должно быть похоже на следующее

      *
!app.py
!local.conf
!requirements.txt
!Dockerfile
!selenium_test/
selenium_test/*
!selenium_test/seleniumTest.py
!selenium_test/seleniumTest2.py
!selenium_test/seleniumTest3.py

Здесь с помощью '*' мы все игнорируем.

Но с '!' мы говорим включить что-то. Сюда включены app.py, local.conf, require.txt и Dockerfile.

Теперь включаем папку selenium_test с '!', потому что нам нужно немного файлов из этой папки.

Но в следующей строке мы исключаем все содержимое папки с selenium_test/*, потому что нам не нужны все файлы из этой папки, а нужны только некоторые из них.

Далее мы указываем включение файлов seleniumTest.py, seleniumTest2.py и seleniumTest3.py, которые существуют в папке selenium_test.

Примечание: если бы мы не добавили 6-ю и 7-ю строки, то 8-я, 9-я и 10-я строки не работали бы, поскольку файлы, указанные в этих строках, не получили бы папку «selenium_test», потому что мы ее уже исключили. в первой строке через '*'.

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