Ігнорувати підкаталоги ігнорованих каталогів у Git


99

Скажімо, я проігнорував каталог, але я хочу ігнорувати певні підкаталоги в ньому. Отже, у мене є установка:

/uploads/
/uploads/rubbish/
/uploads/rubbish/stuff/KEEP_ME/
/uploads/foo/
/uploads/foo/bar/lose/

І я хочу ігнорувати все, крім KEEP_MEкаталогу. Я сподівався б, що ігнорування виглядатиме приблизно так:

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

Але це не працює, як і кілька перестановок на одну тему.

Той, хто працює, є

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

Але це здається трохи обмежувальним і багатослівним?


1
Код, який ви надали, для мене не працював (з використанням git версії 1.9.1). Працював / uploads / *! / Uploads / garbish / / uploads / garbish / *! / Uploads / garbish / stuff / uploads / garbish / stuff / *! / Uploads / garbish / stuff / keep (що схоже на приклад у git-scm.com/docs/gitignore ). Структура моєї папки; └ README.md └ uploads / foo / bar / lose / lose.txt └ uploads / garbish / stuff / keep / keep.txt
gihanchanuka

Відповіді:


119

Відповідно до розділу формату зразка документації gitignore :

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

Тому раніше виключений /uploads/rubbish/stuff/keep/шаблон батьківського каталогу повинен бути виключений, перш ніж заперечувати його вміст:

#ignore everything within /uploads/ 
/uploads/*

#include everything within /uploads/rubbish/stuff/keep
!/uploads/rubbish/stuff/keep/  
!/uploads/rubbish/stuff/keep/*

Щоб додати підкаталоги всередину, /uploads/rubbish/stuff/keep/додайте третій рядок:

!/uploads/rubbish/stuff/keep/**/*

1
Яку версію git ви використовували? Можливо, це щось доступне лише у певних версіях.

Збентежений. Я забув, що опублікував цей коментар. Я все ж працюю. FWIW, я не використовую провісні скісні риски. Я не пам’ятаю, чи це було питання. Я використовую 1.7.2.5.

У мене є глобальний файл gitignore, де я проігнорував усі файли * .zip. Але для конкретного проекту я хочу включити zip-файли. Я додав цей рядок до цього проекту, .gitignoreі він чудово працює !:!*.zip
Jinghao Shi

Я знайшов за необхідне явно вказати довільні каталоги як до, так і після даної папки як при виключенні папки, так і при включенні підпапки . ( Повна відповідь ).
Йодер

Цей метод не працює (станом на git 2.25 - можливо, щось у git змінилося). Я опублікував stackoverflow.com/a/60288435/295691 нижче як виправлення.
user295691

34

Навіть якщо ви щось додасте .gitignore, ви можете змусити git додати це до індексу

git add --force uploads/rubbish/stuff/KEEP_ME/

Однак "KEEP_ME", здається, є каталогом, і git зазвичай не любить порожню папку, тому замість цього слід додати файл-заповнювач, якщо папка порожня

git add --force uploads/rubbish/stuff/KEEP_ME/.keep_me

Єдина проблема з цим полягає в тому, що цей конкретний приклад стосується глобального gitignore, про який я повинен був згадати. Я знаю, що можу змусити додавати елементи, але мені доведеться це робити, якщо додаються нові елементи, а також спочатку для кожного нового сховища. .Keep гарантує, що вміст не ігнорується?
Віль

1
Зробив невеликий тест. Так, ви повинні використовувати git add --forceкожен новий елемент або папку в KEEP_ME. але після цього оновлення просто додаються (наприклад, при виконанні git add -u), ніби файли «неігноровані». .keep_meНічого не робить, його просто файл , так що мерзотник працює на папці.
commonpike

1
git add --forceє неправильним рішенням для цього. Якщо ви переміщуєте каталог навколо або переміщуєте файл в інший каталог, відстеження git видалить файл, але не додасть його в нове місце, і вам доведеться зробити це git add --forceзнову. шляхом ігнорування за загальним шаблоном, git буде відстежувати рух файлу в репо.
Мерлін

Це єдине рішення, яке спрацювало для мене. Моя папка НЕ ​​була проігнорована, але я ніяк не міг додати її. Цей спосіб вирішив це для мене.
Акіто,

6

Намагався з’ясувати, як включити певну папку при виключенні всіх папок із загальним виключенням

**/build

якщо ви додасте в /*кінець загального виключення, ви продовжуєте виключати всі файли збірки**/build/*

Потім ви додаєте ще один рядок, щоб виправити шлях, на який ви хочете бути включеним

!**/folder/build/* 

залишаючи нам gitignore, який читає

**/build/* 
!**/folder/build/* 

2

Буо-Рен Лін та Джон дуже корисні, але мені потрібно було поєднати обидва.

Бажаючи виключити інші підпапки, а також файли в завантажених файлах, я знайшов необхідним чітко вказати довільні каталоги перед даною папкою як при виключенні папки, так і при включенні підпапки.

**/uploads/*
!**/uploads/rubbish/
!**/uploads/rubbish/*

Я також визнав необхідним явно повторно включити як підпапку, так і її вміст, щоб показати як елементи в папці, так і підпапки.


Зітхнути. Тут нуль удачі. На цьому вже годинами. Git 2.20.1
RichieHH

@ HörmannHH Прикро це почути. Можливо, пора задати нове запитання?
Джосія Йодер

2

Рішення, представлене як найбільш прихильна відповідь, є неправильним і легко демонструється як таке.

Почніть з ігнорування всього у завантаженнях / *:

mkdir -p uploads/rubbish/stuff/KEEP_ME
touch uploads/a uploads/rubbish/a uploads/rubbish/stuff/a uploads/rubbish/stuff/KEEP_ME/a
echo '/uploads/*' >> .gitignore
git init
git add .
git commit -m "Initial commit"

Тепер ігноруйте батьківський каталог ігнорованих речей, як зазначено вище:

echo 'uploads/rubbish/stuff/KEEP_ME/' >> .gitignore
echo 'uploads/rubbish/stuff/KEEP_ME/*' >> .gitignore
git status -u

Не відображає файлів без відстеження.

Щоб змусити його працювати, потрібно ігнорувати всі файли під uploads/деревом (а uploads/**/*не лише верхній рівень uploads/*), а потім додати всі батьківські каталоги дерева, яке потрібно зберегти

echo '/uploads/**/*' > .gitignore
echo '!/uploads/rubbish/' >> .gitignore
echo '!/uploads/rubbish/stuff' >> .gitignore
echo '!/uploads/rubbish/stuff/KEEP_ME' >> .gitignore
echo '!/uploads/rubbish/stuff/KEEP_ME/*' >> .gitignore
git status -u

Що дає:

On branch master
...
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        uploads/rubbish/stuff/KEEP_ME/a

Якби ми використовували uploads/*в .gitignoreвище, то всі проміжні файли були б включені, так що , наприклад , uploads/rubbish/aбуде відображатися в команді статус вище.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.