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

310

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

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

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

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

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скоро (git1.8.5 / 1.9) появится --no-indexопция. Смотрите мой ответ ниже
VonC
Примечание: GIT_TRACE_EXCLUDE=1 git statusскоро появится дополнительный способ отладки .gitignoreправил. Смотрите мой отредактированный ответ ниже
VonC
Соответствующее сообщение в блоге: danielcompton.net/2016/04/21/… .
krlmlr

Ответы:

643
git check-ignore -v filename

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

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

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

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

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

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

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

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

Адам Спирс
источник
2
Я использую 1.8.2 и git check-ignoreничего не делаю.
zakdances
3
@yourfriendzak Без тени сомнения, git check-ignoreприсутствует и работает в 1.8.2. Если поведение не соответствует ожидаемому, я предлагаю вам (пере) прочитать страницу руководства, а если это не так, отправьте соответствующий отчет об ошибке в список рассылки git. Просто сказать, что это ничего не делает, не очень полезно. Я ожидаю , что вы, вероятно , запустить его на не игнорировали файл и неправильно ожидает некоторый вывод (хотя я, вероятно , добавить поддержку --show-unmatchedв --verboseрежиме вывода в будущем).
Адам Спирс
1
@AdamSpiers ты прав. Я должен был указать, что при выполнении команды ничего не печатается. Нет сообщения об ошибке, нет сообщения об успехе, нет информации. Просто следующая пустая подсказка. Итак, правильно ли я предположить, что при определенных обстоятельствах поведение «нет результата» ожидается?
zakdances
1
@AdamSpiers большое спасибо за это! После 3 дней расследования вы только что помогли мне отследить причину поломки сборки из-за глобально игнорируемого файла в .gitignore_global! Я даже не знал, что это была вещь!
BenBtg
3
Не каждый день можно увидеть, как разработчик Stack Overflow вносит так много изменений для реализации функции разработчика. Вау и уважаю.
user3613932
18

Обновление 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.
VonC
источник
4

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

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 
edoloughlin
источник
1

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

* .sublime-project

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

rekordboy
источник