Неотслеживаемые файлы не отображаются в состоянии git

У меня есть проект со следующей структурой папок:

Все файлы проекта находятся в папке base_fldr. Также у меня есть несколько папок внутри base_fldr, которые называются sub_fldr1 и sub_fldr2. Эти подпапки также содержат некоторые файлы.

Если я изменяю какие-либо файлы внутри моего base_fldr или base_fldr\sub_fldr\, то git status показывает их как измененные. Также, если я добавлю новый файл в base_fldr, git status покажет его как неотслеживаемый файл.

Моя проблема в том, что если я добавлю новый файл в base_fldr\sub_fldr\, то в состоянии git файл не будет отслежен. Он даже не даст никакой информации о файле.

Файл или его расширение НЕ в моем списке.gitignore. Также я попробовал git add sub_fldr \ file_name, но он не выдал ошибку и не добавил файл в индекс.

Есть идеи, что здесь происходит? Спасибо!

8 ответов

Решение

Я понял, что происходит не так. По сути, первая строка в моем файле.gitignore - "*/". Это приводит к тому, что любой файл, добавленный в подкаталог, игнорируется командой git status. Но забавно то, что если я изменяю какие-либо файлы в подпапке, git status правильно показывает их как измененные, поскольку файл уже находится в репозитории git, но игнорирует новые файлы в подпапке.

Я исправил свою проблему, удалив строку в файле.gitignore, чтобы не игнорировать изменения в подпапках, затем добавил новые файлы в индекс, а затем снова добавил строку в.gitignore, чтобы он игнорировал любые созданные файлы в подпапках.

Спасибо всем за ответы.

Это вероятно потому, что ваш каталог base_fldr\sub_fldr\ не отслеживается, если вы запустите:

git add base_fldr\sub_fldr\

Из корня вашей рабочей копии он автоматически добавит каталог и другие файлы и каталоги в этом каталоге.

По умолчанию git не показывает файлы в каталогах, которые не отслеживаются.

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

git update-index --assume-unchanged my-tracked-file-that-is-awol

В итоге я отказался от этой идеи, но забыл отменить команду, поэтому последующие изменения этого и других --assume-неизмененных файлов полностью отсутствовали в:

git status -u --ignored

Мне потребовалось некоторое время, чтобы понять, что происходит, но мне просто пришлось отменить команду с помощью:

git update-index --no-assume-unchanged my-tracked-file-that-is-awol

У вас есть .git подкаталог внутри вашего sub_fldr каталог? Git может подумать, что вы пытаетесь использовать субмодули.

Для устранения проблемы, подобной этой, посмотрите, .gitignore Файл является виновником, соблюдая следующие два вывода

Смотрите https://git-scm.com/docs/git-ls-files

  1. git ls-files --other --directory --exclude-standard

Это покажет все неотслеживаемые файлы, подчиняясь .gitignore файл.

  1. git ls-files --other --directory

Это покажет все неотслеживаемые файлы, не подчиняясь .gitignore файл.

Какие файлы присутствуют в выводе 2, но нет в выводе 1, не отображаются неотслеживаемыми из-за какого-либо флага в вашем .gitignore файл

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

У вас может возникнуть эта ошибка с файлами, которые были изменены с помощьюchmod.

С использованиемgit status -uвы можете увидеть их в «Неотслеживаемых файлах», но сgit diffвсе они не показали никакой разницы.

С 2011 года это было впервые исправлено в Git v1.8.3-rc0 (апрель 2013 года).
Он исправляет несколько проблем в коде для обхода рабочего дерева, чтобы найти неотслеживаемые и / или игнорируемые файлы, очищает и оптимизирует путь кода в целом.

См совершать 0aaf62b, совершать defd7c7, совершают 8aaf8d7, совершают b07bc8c, совершают 95c6f27, совершают 6cd5c58, совершают 46aa2f9, совершают 5bd8e2d, совершают be8a84c, совершают c94ab01, совершают 184d2a8, совершают 0104c9e, совершают 289ff55, совершают 560bb7a (15 апреля 2013) по Карстен Blees (kblees).
(Слияние Junio ​​C Hamano -gitster- в коммите 7093d2c, 23 апреля 2013 г.)

dir.c: заставить 'git-status--ignored' работать в ведущих каталогах

Подписано: Карстен Блис

'git status--ignored path/'не перечисляет игнорируемые файлы и каталоги в'path'если какой-то компонент'path'классифицируется как неотслеживаемая.

Отключить DIR_SHOW_OTHER_DIRECTORIESфлаг при просмотре ведущих каталогов. Это предотвращаетtreat_leading_path() с DIR_SHOW_IGNORED флаг от прерывания в неотслеживаемой директории верхнего уровня.

В качестве побочного эффекта это также исключает рекурсивное сканирование каталогов для каждого уровня ведущего каталога, так как treat_directory() больше не могу звонить read_directory_recursive() когда звонят из treat_leading_path().


Но, 6 лет спустя (конец 2019 г.), с Git 2.25 (1 квартал 2020 г.), различные исправления API обхода каталогов... верните то самое исправление, которое было показано выше, и повторно внедрите его.

См. Commit 6836d2f (20 декабря 2019 г.) от Junio ​​C Hamano (gitster).
См. Фиксацию c847dfa, фиксацию 777b420, фиксацию b9670c1 (19 декабря 2019 г.) и фиксацию c5c4edd, фиксацию 072a231, фиксацию 2f5d384, фиксацию a2b1336, фиксацию 452efd1 (10 декабря 2019 г.) Элайджа Ньюрен (newren).
(Слияние Junio ​​C Hamano -gitster- в коммите d2189a7, 25 декабря 2019 г.)

Revert "dir.c: сделать 'git-status--ignored'работа в ведущих каталогах "

Подписано: Элайджа Ньюрен

Зафиксируйте be8a84c52669 ("[dir.c](https: //github.com/git/git/blob/a2b13367fe55bdeb10862f41aff3e2446b63e171/dir.c): make 'git-status--ignored'работа в ведущих каталогах ", 2013-04-15, Git v1.8.3-rc0 - merge) отметил, что

git status--ignored <SOMEPATH>

не будет перечислять игнорируемые файлы и каталоги в <SOMEPATH> если <SOMEPATH> не отслеживались, и изменили поведение, чтобы оно отображало их.

Однако это было сделано с помощью хака, нарушившего согласованность; он покажет пути под<SOMEPATH> иначе, чем простой

git status--ignored | grep <SOMEPATH>

покажет им.

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

Некоторая история может быть полезна:

Очень, очень похожий случай на отменяемый нами коммит был поднят в коммите 48ffef966c76 ("ls-files: fix overeager pathspec optimisation", 08.01.2010, Git v1.7.0-rc0 - merge); но на самом деле все пошло в несколько противоположном направлении.

В этом коммите упоминалось, как

git ls-files -o --exclude-standard t/

используется для отображения неотслеживаемых файлов в t/ даже когда t/ был проигнорирован, а затем изменил поведение, чтобы перестать показывать неотслеживаемые файлы в игнорируемом каталоге.

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

Причина всей этой несогласованности, когда указывается один pathspec вместо нуля или двух, заключается в том, что общие префиксы pathspecs отправляются через другой набор проверок (в treat_leading_path()), чем при обычном обходе файлов / каталогов (они проходят через read_directory_recursive() а также treat_path()).

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

REVERT https://github.com/git/git/commit/be8a84c526691667fc04a8241d93a3de1de298ab, за исключением вместо удаления TestCase добавил он, изменить его, чтобы проверить правильность и последовательное поведение.

А также:

dir: исправлены проверки общего каталога префиксов

Подписано: Элайджа Ньюрен

Много лет назад логика обхода каталогов имела оптимизацию, которая всегда рекурсивно возвращалась в любой каталог, который был общим префиксом для всех указателей пути, без перехода по ведущим каталогам, чтобы перейти к желаемому каталогу.

Таким образом,

git ls-files -o .git/                        # case A

заметил бы, что .git/ был общим префиксом для всех спецификаций пути (так как это единственный указанный путь), а затем перейти к нему и начать показывать неизвестные файлы в этом каталоге.

К сожалению, .git/ это не каталог, в который мы должны переходить, что сделало эту оптимизацию проблематичной.

Это также коснулось таких случаев, как:

git ls-files -o --exclude-standard t/        # case B

где t/ был в .gitignore файл и, следовательно, не интересен и не должен использоваться повторно.

Это также повлияло на такие случаи, как:

git ls-files -o --directory untracked_dir/   # case C

где untracked_dir/ действительно не отслеживается и поэтому интересен, но --directory Флаг означает, что мы хотим показать только сам каталог, а не возвращаться в него и начинать перечисление неотслеживаемых файлов под ним.

Ошибки класса B были отмечены и исправлены в коммитах 16e2cfa90993. ("read_directory(): дальнейшее разделение treat_path()", 08.01.2010) и 48ffef966c76 ("ls-files: fix overeager pathspec optimisation", 08.01.2010, Git v1.7.0-rc0 - merge), идея заключалась в том, что мы сначала хотели проверить, интересен ли общий префикс.

В предыдущем патче отмечалось, что treat_path() нельзя использовать при проверке общего префикса, потому что treat_path() требует dir_entry() и мы не читали никаких каталогов на момент проверки общего префикса.

Итак, этот патч раскололся treat_one_path() снаружи treat_path().

Последний патч затем создал новый treat_leading_path() который дублировал вручную кусочки treat_path() это не могло быть разбито, а затем позвонить treat_one_path() на остаток.

У этого подхода было три проблемы:

  • Дублированная логика в treat_leading_path() случайно пропустил проверку на особые пути (например, is_dot_or_dotdot и соответствие ".git"), из-за чего ошибки типа case A продолжают оставаться проблемой.
  • В treat_leading_path() логика предполагала, что мы должны пройти туда, где path_treatment не был path_none, то есть это увековечило ошибки типа C.
  • Это означало, что у нас была логика разделения, которую нужно было синхронизировать, рискуя тем, что люди внесут новые несоответствия (например, в фиксацию be8a84c52669, которую мы вернули ранее в этой серии, или в фиксации df5bcdf83ae, которую мы исправим в следующей фиксации)

Решите большинство этих проблем, сделав treat_leading_path() не только перебирать каждый компонент ведущего пути, но и вызывать treat_path() прямо на каждом.

Для этого нам нужно создать синтетический dir_entry, но это займет всего несколько строк.

Затем обратите внимание на path_treatment результат мы получаем от treat_path() и не лечить path_excluded, path_untracked, а также path_recurse все так же, как path_recurse.

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