Подтвердить что ты не робот

.gitignore белый список в каталоге и его содержимое

Я пытаюсь перечислить каталог (и его содержимое) в списке поставщиков в каталоге Zend Framework 2.

Оригинальный файл .gitignore в /vendor выглядит следующим образом:

# Add here the vendor path to be whitelisted
# Ex: for composer directory write here "!composer" (without quotes)
!.gitignore
*

Теперь я хотел бы добавить белый список в каталог SupplierName, который не должен быть слишком сложным, я думал. Я прочитал документы о gitignore и попробовал следующие конфигурации:

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

# Add here the vendor path to be whitelisted
!SupplierName
# Ex: for composer directory write here "!composer" (without quotes)
!.gitignore
*

Сразу после этого я выполнил git status, который не показывал каталог vendor/SupplierName. git add vendor/SupplierName отобразилось следующее сообщение:

Следующие пути игнорируются одним из ваших файлов .gitignore: vendor/SupplierName

Вторая попытка

# Add here the vendor path to be whitelisted
# Ex: for composer directory write here "!composer" (without quotes)
!SupplierName
!.gitignore
*

Сразу после этого я выполнил git status, который не показывал каталог vendor/SupplierName. git add vendor/SupplierName отобразилось следующее сообщение:

Следующие пути игнорируются одним из ваших файлов .gitignore: vendor/SupplierName

Третья попытка

# Add here the vendor path to be whitelisted
# Ex: for composer directory write here "!composer" (without quotes)
!.gitignore
*
!SupplierName

Сразу после этого я выполнил git status, который не показывал каталог vendor/SupplierName. git add vendor/SupplierName , похоже, работает. Но теперь, когда я хочу добавить файл Module.php(и некоторые другие файлы, подкаталоги и т.д.), Произойдет следующее. git add vendor/SupplierName/Module.php

Следующие пути игнорируются одним из ваших файлов .gitignore: vendor/SupplierName/Module.php

# Add here the vendor path to be whitelisted
# Ex: for composer directory write here "!composer" (without quotes)
*
!.gitignore
!SupplierName
!SupplierName/
!SupplierName/*

Позволяет мне добавлять файлы непосредственно в vendor/SupplierName, но git add vendor/SupplierName/config/module.config.php все еще приводит к

Следующие пути игнорируются одним из ваших файлов .gitignore: vendor/SupplierName/config/module.config.php

Я искал проблемы с рекурсивным "белым списком", потому что это проблема, но ничего не получилось.

4b9b3361

Ответ 1

Вы можете использовать 2 .gitignore файлы для достижения желаемого результата:

# vendor/.gitignore
*
!.gitignore
!SupplierName/
!SupplierName/*

# vendor/SupplierName/.gitignore
!*

Я тестировал это с помощью тестового репо и, похоже, работал у меня в добавлении файлов на столько уровней, которые находятся под каталогом vendor/SupplierName.

$ git add .

$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   vendor/.gitignore
#   new file:   vendor/SupplierName/.gitignore
#   new file:   vendor/SupplierName/a
#   new file:   vendor/SupplierName/b
#   new file:   vendor/SupplierName/c
#   new file:   vendor/SupplierName/d
#   new file:   vendor/SupplierName/dir1/d
#   new file:   vendor/SupplierName/dir1/dir4/dir5/dir6/dir7/dir8/dir9/dir10/somefile
#   new file:   vendor/SupplierName/dir1/dir4/f1
#   new file:   vendor/SupplierName/dir1/dir4/f2
#   new file:   vendor/SupplierName/dir1/dir4/f3
#   new file:   vendor/SupplierName/dir1/dir4/f4
#   new file:   vendor/SupplierName/dir1/e
#   new file:   vendor/SupplierName/dir1/f
#   new file:   vendor/SupplierName/dir3/dir6/f5
#   new file:   vendor/SupplierName/dir3/dir6/f6
#   new file:   vendor/SupplierName/dir3/dir6/f7
#   new file:   vendor/SupplierName/dir3/dir7/f8
#   new file:   vendor/SupplierName/e
#

Ответ 2

Вы также можете добиться этого только одним файлом .gitignore (в корне вашего проекта):

/*
!/.gitignore
!/vendor
/vendor/*
!/vendor/SupplierName

Ответ 3

Нашла интересную статью: https://jasonstitt.com/gitignore-whitelisting-patterns

Все кредиты Джейсону Ститту. Тексты копируются с сайта выше:

Игнорировать все, а затем добавить определенные поддеревья

# Ignore everything
*
# But descend into directories
!*/
# Recursively allow files under subtree
!/subtree/**
# You can be specific with these rules
!/some/other/deep/path/**
!.gitignore 

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

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

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

Игнорировать корневой каталог, затем добавить целые поддеревья

# Ignore everything in the root
/*
# Un-ignore all of subtree
!/subtree/
!.gitignore 

Этот шаблон несколько грубее, чем предыдущий. Правило /* будет игнорировать элементы в корне репозитория структуру каталогов, поэтому, как только вы перейдете в белый список из каталога, все содержимое каталогов также будет разрешено, даже без использования подстановочные знаки * или **.

Игнорировать все в каталоге, но сохранить пустую директорию

*
!.gitignore

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

Ответ 4

У меня была аналогичная проблема при переходе с CVS на Git.

В отличие от CVS, Git не смотрит на каталоги, он фокусируется на файлах.

Например, вы не можете игнорировать каталог "a" , но вы не можете игнорировать все файлы в каталоге "a" так:! a/*

То же самое верно для подкаталогов.

Если в каталоге "a" есть подкаталог "b", и вы игнорируете "! a/*", тогда вы все равно получите все файлы в "a/b".

Таким образом, вы должны игнорировать это слишком "! a/b/*" и т.д. для всех подкаталогов, которые вы хотите иметь в белом списке.

Вам нужен только один файл .gitignore.

чтобы вы получили что-то вроде:

# ignore everything
*
# except for .gitignore files in the current directory
!.gitignore
# and all files in directory a
!a/*
#and all files in subdirectory b
!a/b/*

С этим вы все равно получите файлы из a/c и a/b/c. Я не уверен, есть ли временное решение для рекурсии вниз подкаталогов.

Ответ 5

Сначала вы должны включить все в черный список, а затем сделать все каталоги и субтитры в белом списке. Например, я хочу только добавить DIR /opt/source/, DIR /opt/nginx/ и FILE /home/test/.opt/hello.txt в белый список, написать файл .gitignore, как это сделать, чтобы он работал:

/*
!/.gitignore
!/opt
/opt/*
!/opt/source/
!/opt/nginx/
!/home
/home/*
!/home/test
/home/test/*
!/home/test/.opt
/home/test/.opt/*
!/home/test/.opt/hello.txt

Ответ 6

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

'use strict';

// Generating a "whitelist" wherein you only want a specific folder to be
// affected requires following .gitignore-style rules.
// https://github.com/prettier/prettier/issues/3328
//
// Handcrafting these rules is hard to reason about and error-prone, so I'm
// going to generate them.
// See: https://github.com/prettier/prettier/issues/3328
// And: https://git-scm.com/docs/gitignore
//

const path = require('path');

const whitelistDir = '/themes/simple/src/';

function generateIgnoreRule(dir) {
    let output = '# Auto-generated by ' + path.basename(__filename) + '\n';
    output += '# Exclude everything except '' + dir + ''\n';
    // Add exclude everything rule
    output += '/*' + '\n';

    // Split by path
    const parts = dir.split('/');
    if (parts[0] === '') {
        // Remove first item if its blank
        parts.shift();
    }
    if (parts[parts.length - 1] === '') {
        // Remove last item if its blank
        parts.pop();
    }

    let totalPart = '';
    for (let part of parts) {
        totalPart += '/' + part;
        output += '!' + totalPart + '\n';
        if (part !== parts[parts.length - 1]) {
            output += totalPart + '/*' + '\n';
        }
    }
    return output;
}

console.log(generateIgnoreRule(whitelistDir));
console.log(
    '\nCopy the above rules out of the console output and paste into your .gitignore / .prettierignore'
);

Ответ 7

Это связано с первым методом @Simon Lang (с благодарностью Jason Stitt), но применимо к более широкому кругу случаев.

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

Затем вы можете сделать следующее в своем корневом файле .gitignore:

# ignore all files and folders in '/vendor/' and in its descendants
/vendor/**

# negated pattern to un-exclude all *folders* at any depth relative to 'vendor/'
# as always git will ultimately ignore the folders for which you don't
# subsequently un-exclude any *files*.
!/vendor/**/

# negated pattern to un-exclude all files and folders at any depth below the deep
# path that contains files you want in git
!/vendor/supplier/version/module/component/src/**

Каждый экземпляр двойной звездочки имеет решающее значение. Например, конечный vendor/** сопоставляет все внутри - все файлы и каталоги в vendor с бесконечной глубиной, и поэтому исключает всех его потомков.

В "нормальном" подстановочном правиле gitignore, таком как *.exe или *, сопоставление метасимвола глобуса обнаруживает любой файл в любом каталоге, поскольку путь является неограниченным. Неограниченный путь делает здесь тяжелую работу, а не расширение подстановочного знака. Как только вы попытаетесь ограничить область действия игнорирования подкаталогом своего корня, этот тяжеловес исчезнет, и вы сразу же натолкнетесь на неспособность * спуститься в дерево.

Ответ саймона работает, оставляя кончик исходного пути исключения без ограничений. Изначально он исключает каждый файл (на любой глубине) в каталоге, который содержит файл .gitignore. Мой дает вам гибкость в применении этого подхода исключить все к подкаталогам, используя ** для сопоставления глобстар /. Вы можете добиться того же эффекта, имея несколько файлов .gitignore и используя технику Саймона в файле .gitignore, расположенном в /vendor/.gitignore, но это больше для поддержки.

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

*
!*/
!a/b/c/d/**

тому, который был похож на это

/**
!**/
!a/b/c/d/**

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