Как на самом деле работают правила исключения .gitignore? - PullRequest
139 голосов
/ 09 июня 2010

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

У меня есть следующая структура каталогов из двух файлов (foo, bar) в новом репозитории git (пока нет коммитов):

a/b/c/foo
a/b/c/bar

Очевидно, что 'git status -u' показывает:

# Untracked files:
...
#       a/b/c/bar
#       a/b/c/foo

Я хочу создать файл .gitignore, который игнорирует все, что находится внутри / b / c, но не игнорирует файл 'foo'.

Если я создаю .gitignore таким образом:

c/

Затем в 'git status -u' игнорируются foo и bar:

# Untracked files:
...
#       .gitignore

Как я и ожидал.

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

c/
!foo

Согласно справочной странице gitignore, я ожидаю, что это сработает. Но это не так - все равно игнорирует foo:

# Untracked files:
...
#       .gitignore

Это тоже не работает:

c/
!a/b/c/foo

Ни то, ни другое:

c/*
!foo

Дает:

# Untracked files:
...
#       .gitignore
#       a/b/c/bar
#       a/b/c/foo

В этом случае, хотя foo больше не игнорируется, bar также не игнорируется.

Порядок правил в .gitignore, похоже, тоже не имеет значения.

Это также не делает то, что я ожидал:

a/b/c/
!a/b/c/foo

Тот игнорирует как foo, так и bar.

Одна ситуация, которая работает, если я создаю файл a / b / c / .gitignore и вставляю туда:

*
!foo

Но проблема в том, что со временем в / b / c будут другие подкаталоги, и я не хочу добавлять отдельный .gitignore в каждый из них - я надеялся создать «основанный на проекте» '.gitignore файлы, которые могут находиться в верхнем каталоге каждого проекта и покрывать всю «стандартную» структуру подкаталогов.

Это также кажется эквивалентным:

a/b/c/*
!a/b/c/foo

Это может быть самая близкая вещь к "работе", которую я могу достичь, но необходимо указать полные относительные пути и явные исключения, что будет проблемой, если у меня много файлов с именем 'foo' на разных уровнях дерева подкаталогов.

В любом случае, либо я не совсем понимаю, как работают правила исключения, либо они вообще не работают, когда каталоги (а не подстановочные знаки) игнорируются - правилом, оканчивающимся на /

Может кто-нибудь пролить свет на это?

Есть ли способ заставить gitignore использовать что-то разумное, например, регулярные выражения, вместо этого неуклюжего синтаксиса на основе оболочки?

Я использую и наблюдаю это с помощью git-1.6.6.1 на Cygwin / bash3 и git-1.7.1 на Ubuntu / bash3.

Ответы [ 5 ]

141 голосов
/ 09 июня 2010
/a/b/c/*
!foo

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

Думайте об исключениях какговорить «но не этот», а не «но включать это» - «игнорировать этот каталог (/a/b/c/), но не этот (foo)» не имеет большого смысла;msgstr "игнорировать все файлы в этом каталоге (/a/b/c/*), но не этот (foo)".Чтобы процитировать man-страницу:

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

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

24 голосов
/ 07 марта 2012

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

/a/**/*
!/a/**/foo

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

6 голосов
/ 06 февраля 2011

Вот еще один вариант:

*
!/a*
!/a/*
!/a/*/*
!/a/*/*/*

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

4 голосов
/ 18 февраля 2013

На более общей ноте git1.8.2 будет включать патч (также в его v4 , , вызванный некоторым вопросом переполнения стека ) из Adam Spiers об определении, какое gitignore правило фактически игнорирует ваш файл.

См. git1.8.2 заметки о выпуске и вопрос SO ", какое правило gitignore игнорирует мой файл ":
это будет команда git check-ignore.

4 голосов
/ 10 ноября 2010

это определенно не ясно из справочной страницы .gitignore. Это работает:

*
!/a
!/a/b
!/a/b/c
!/a/b/c/foo

# don't forget this one
!.gitignore

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

...