Как работают отрицательные шаблоны в .gitignore?

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

В качестве минимального примера у меня есть следующая структура каталогов:

C:/gittest
 -- .gitignore
 -- aaa/
   -- bbb/
     -- file.txt
   -- ccc/
     -- otherfile.txt

и в моем файле gitignore у меня есть следующее:

aaa/
!aaa/ccc/

Мое понимание (на основе эта страница doc) заключается в том, что файл aaa/ccc/otherfile.txt не следует игнорировать, но в факт git игнорирует все под aaa.

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

Кстати, это в Windows с msysgit 1.7.0.2.

Ответ 1

Я думаю, что вы действительно хотите сделать:

aaa/*
!aaa/ccc

Вы говорите "не смотрите в aaa", поэтому он даже не рассматривает путь aaa/ccc. Если вы используете подстановочный знак, он все еще читает содержимое aaa, тогда каждая запись соответствует шаблону и игнорируется, за исключением aaa/ccc, который возвращается обратно.

Ответ 2

Если вы хотите исключить все в aaa, но включите aaa/ccc и все под ним, вы должны использовать:

aaa/*
!aaa/ccc
!aaa/ccc/*

Первая строка сообщает git игнорировать все ниже aaa, вторая говорит ему не игнорировать папку aaa/ccc, которая фактически "разрешает" третью строку, которая затем говорит ей не игнорировать все под aaa/ccc.

Ответ 3

Если кто-то еще не видит новые незанятые элементы в git status, запустив git update-index, перед тем, как помочь, он сможет git увидеть изменения (по крайней мере, в версии 1.9.x из gitbash).