Объясните, какое правило gitignore игнорирует мой файл

Есть ли способ узнать, почему какой-то файл игнорируется с помощью git (то есть какое правило в файле .gitignore вызывает игнорирование файла)?

Представьте, что у меня есть этот (или гораздо более сложный сценарий) с сотнями папок и десятками файлов .gitignore:

/
-.gitignore
-folder/
    -.gitignore
    -subfolder/
              -.gitignore
              -file.txt

Если я запустил git add folder/subfolder/file.txt git, могу пожаловаться на его игнорирование:

The following paths are ignored by one of your .gitignore files:
folder/subfolder/file.txt
Use -f if you really want to add them.

Есть ли способ узнать, какие из возможных .gitignore имеют правило игнорировать этот файл, а также показать правило? Как:

The following paths are ignored by your folder/.gitignore file (line 12: *.txt)
folder/subfolder/file.txt
Use -f if you really want to add them.

Или просто:

$ git why-is-ignored folder/subfolder/file.txt
folder/.gitignore:12:*.txt

Ответ 1

git check-ignore -v filename

Смотрите man-страницу для более подробной информации.

Исходный ответ следует:

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

ОБНОВЛЕНИЕ: Вау, это было намного сложнее, чем я ожидал. Внутренности git exclude обрабатываются довольно загадочно. Во всяком случае, здесь почти законченная серия коммитов, которые применяются к сегодняшней master ветке разработки. Набор тестов завершен на 99%, но я еще не закончил обработку опции --stdin. Надеюсь, я справлюсь с этим в эти выходные, а затем отправлю свои патчи в список рассылки git.

Тем временем я определенно приветствую тестирование от любого, кто сможет это сделать - просто клонировать с моего git fork, проверить ветку check-ignore и скомпилировать его как обычно.

ОБНОВЛЕНИЕ 2: Это сделано! Последняя версия находится на github, как указано выше, и я отправил серию патчей в список рассылки git для экспертной оценки. Давай посмотрим, что они думают...

ОБНОВЛЕНИЕ 3: После еще нескольких месяцев взлома/обзоров патчей/обсуждений/ожидания я рад сообщить, что эта функция достигла ветки git master и будет доступна в следующем выпуске (ожидается 1.8.2) 8 марта 2013 г.) Здесь check-ignore страница check-ignore руководства. Фу, это было намного больше работы, чем я ожидал!

ОБНОВЛЕНИЕ 4: Если вам интересна полная история о том, как этот ответ развивался и какая функция стала реализовываться, ознакомьтесь с выпуском № 32 подкаста GitMinutes.

Ответ 2

Обновление git 2.8 (март 2016 года):

GIT_TRACE_EXCLUDE=1 git status

Смотрите " Способ проверки файла .gitignore ".

Это дополняет git check-ignore -v описанный ниже.


Оригинальный ответ: сентябрь 2013 г. (git 1.8.2, затем 1.8. 5+):

git check-ignore снова улучшается в git 1.8.5/1.9 (4 квартал 2013 года):

" git check-ignore " следует тем же правилам, что и " git add " и " git status ", в том смысле, что механизм игнорирования/исключения не действует на пути, которые уже отслежены.
С параметром --no-index он может использоваться для диагностики того, какие пути, которые должны были быть проигнорированы, были ошибочно добавлены в индекс.

Смотрите коммит 8231fa6 на https://github.com/flashydave:

check-ignore настоящее время показывает, как правила .gitignore будут обрабатывать неотслеживаемые пути. Отслеживаемые пути не генерируют полезный вывод.
Это предотвращает отладку того, почему путь стал отслеживаться неожиданно, если этот путь не был сначала удален из индекса с помощью git rm --cached <path>.

Опция --no-index говорит команде обойти проверку на наличие пути в индексе и, следовательно, позволяет также проверять отслеживаемые пути.

Хотя это поведение отличается от характеристик git add и git status его вариант использования вряд ли вызовет путаницу среди пользователей.

Тестовые сценарии дополнены, чтобы проверить эту опцию в сравнении со стандартным игнорированием для обеспечения правильного поведения.


--no-index::

Не смотрите в индекс при проведении проверок.
Это можно использовать:

  • отладить, почему путь стал отслеживаться, например, git add. и не был проигнорирован правилами, как ожидается пользователем или
  • при разработке шаблонов, включающих отрицание, чтобы соответствовать пути, ранее добавленному с помощью git add -f.

Ответ 3

Я не могу найти что-либо на странице man, но здесь быстрый и грязный script, который проверяет ваш файл в каждом родительском каталоге, чтобы узнать, может ли он быть git -add'ed. Запустите его в каталоге, содержащем файл проблемы, как:

test-add.sh STOP_DIR FILENAME

где STOP_DIR - это каталог верхнего уровня проекта Git, а FILENAME - это имя файла проблемы (без пути). Он создает пустой файл с тем же именем на каждом уровне иерархии (если он не существует) и пытается a git add -n посмотреть, можно ли его добавить (он очищается после себя). Он выводит что-то вроде:

FAILED:    /dir/1/2/3
SUCCEEDED: /dir/1/2

script:

#!/usr/bin/env bash
TOP=$1
FILE=$2
DIR=`pwd`
while : ; do
  TMPFILE=1
  F=$DIR/$FILE
  if [ ! -f $F ]; then
    touch $F
    TMPFILE=0
  fi
  git add -n $F >/dev/null 2>&1
  if [ $? = 0 ]; then
    echo "SUCCEEDED: $DIR"
  else
    echo "FAILED:    $DIR"
  fi
  if [ $TMPFILE = 0 ]; then
    rm $F
  fi
  DIR=${DIR%/*}
  if [ "$DIR" \< "$TOP" ]; then
    break
  fi
done 

Ответ 4

Чтобы добавить к основному ответу использование git check-ignore -v filename (спасибо BTW), я обнаружил, что мой файл .gitignore блокирует все, потому что после символа подстановки был символ новой строки, поэтому у меня было:

*.sublime-project

В качестве примера. Я только что удалил перевод строки и вуаля! Это было исправлено.