Объясните, какое правило 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

4 ответа

Решение
git check-ignore -v filename

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

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

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

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

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

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

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

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

Обновление 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 msgstr "можно использовать для диагностики, какие пути, которые должны были быть проигнорированы, были ошибочно добавлены в индекс.

Смотрите коммит 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,

А может и не быть .gitignore - 3 возможных причины игнорирования

Файл может быть проигнорирован по следующим причинам:

  1. .gitignore
  2. git update-index --skip-worktree
  3. git update-index --assume-unchanged

Кроме того, файл может быть отклонен, если он находится в .gitignore И уже поставлено в индекс / кеш.

Чтобы проверить перечисленные выше случаи:

  1. Для двух случаев .gitignore исключает, сравните вывод:

    • git check-ignore --verbose --non-matching --no-index file1 file2 file3
    • git check-ignore --verbose --non-matching file1 file2 file3
  2. git ls-files file1 file2 file3 | grep -E '^S'

  3. git ls-files file1 file2 file3 | grep -E '^[[:lower:]]'

Это слишком сложно, просто дайте мне псевдоним!

Следующие псевдонимы охватывают все перечисленные выше случаи:

ignore = !"bash -c 'diff --unified=999999999 --color=always <(echo a; git check-ignore --verbose --non-matching --no-index . \"$@\") <(echo b; git check-ignore --verbose --non-matching . \"$@\")' - \"$@\" | tail -n+7; git hidden \"$@\" # Show ignore status of arguments. Files included by index are tagged with prepended '+'."
hidden = !"git ls-files -v -- \"$@\"| grep -E '^(S|[[:lower:]])' # S means update-index --skip-worktree, and lower first letter means --assume-unchanged."

Комментарий и финал " являются частью строки, которую нужно скопировать на ваш .gitconfig.

Применение:

git ignore file1 file2 file3

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

test-add.sh STOP_DIR FILENAME

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

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

Сценарий:

#!/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 

Контекст: у меня была очень похожая проблема, я не мог найти, какое правило игнорировало мой файл / папку. Я старался
git check-ignore -v filename
но это не дало мне результата, или результатом был номер строки с пустой строкой в ​​моем файле.gitignore.
Итак, проблема заключалась в том, что мой файл игнорировался не моим локальным файлом.gitignore, а моим локальным файлом core.excludesfile (который не включен в мой репозиторий) .

Решение: я искал место для файла с помощью этой команды:
git config core.excludesfile
потом открываю и удаляю проблемную строчку и все.

Ссылка: вы также можете посмотреть здесь дополнительные объяснения.

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

* .sublime-project

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

Другие вопросы по тегам