Как на самом деле работают правила исключения .gitignore?
Я пытаюсь решить проблему gitignore в большой структуре каталогов, но для упрощения моего вопроса я сводил ее к следующему.
У меня есть следующая структура каталогов из двух файлов (foo, bar) в новом репозитории git (до сих пор не зафиксировано):
a/b/c/foo
a/b/c/bar
Очевидно, что статус 'git -u' показывает:
# Untracked files:
...
# a/b/c/bar
# a/b/c/foo
Я хочу создать файл .gitignore, который игнорирует все внутри a/b/c, но не игнорирует файл 'foo'.
Если я создаю .gitignore таким образом:
c/
Тогда статус 'git -u' показывает как foo, так и bar как игнорируемые:
# Untracked files:
...
# .gitignore
Что, как я ожидаю.
Теперь, если я добавлю правило исключения для foo, таким образом:
c/
!foo
Согласно man-странице 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
Но проблема в том, что в конечном итоге будут другие подкаталоги под a/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.
Ответы
Ответ 1
/a/b/c/*
!foo
Кажется, работает для меня (git 1.7.0.4 на Linux). *
важен, поскольку в противном случае вы игнорируете сам каталог (поэтому git не будет выглядеть внутри) вместо файлов в каталоге (что позволяет исключить).
Подумайте об исключениях как о "но не об этом", а не "но включите это" - "игнорировать этот каталог (/a/b/c/
), но не этот (foo
)" не имеет большого смысла; msgstr "игнорировать все файлы в этом каталоге (/a/b/c/*
), но не этот (foo
)". Чтобы процитировать страницу man:
Дополнительный префикс! что отрицает шаблон; любой сопоставимый файл, исключенный предыдущим шаблоном, снова будет включен.
i.e, файл должен быть исключен уже для включения снова. Надеюсь, что проливает свет.
Ответ 2
У меня похожая ситуация, мое решение заключалось в использовании:
/a/**/*
!/a/**/foo
Это должно работать для произвольного количества промежуточных каталогов, если я правильно прочитал **
.
Ответ 3
Вот еще один вариант:
*
!/a*
!/a/*
!/a/*/*
!/a/*/*/*
Это игнорирует каждый файл и каталог, за исключением файлов/каталогов, расположенных на трех уровнях в пределах.
Ответ 4
это определенно не понятно из справочной страницы .gitignore. Это работает:
*
!/a
!/a/b
!/a/b/c
!/a/b/c/foo
# don't forget this one
!.gitignore
Как упоминалось Крисом, директория даже не открывается, если она исключена. Поэтому, если вы хотите игнорировать *, но некоторые файлы, вы должны создать путь к тем файлам, как указано выше. Для меня это удобно, потому что я хочу сделать обзор кода в 1 файле библиотеки, и если я хочу сделать другое позже, просто добавлю его, а все остальное будет проигнорировано.
Ответ 5
В более общем случае git1.8.2 будет включать патч (также в своем v4, , вызванный некоторым вопросом) от Adam Spiers об определении того, какое правило gitignore
фактически игнорирует ваш файл.
Смотрите примечания к выпуску git1.8.2 и вопрос SO , в котором правило gitignore игнорирует мои файл ":
это будет команда git check-ignore
.