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

647

Я промочил ноги с помощью Git и имею следующую проблему:

Дерево исходного кода моего проекта:

/
|
+--src/
+----refs/
+----...
|
+--vendor/
+----...

У меня есть код (в настоящее время MEF) в моей ветке поставщика, который я скомпилирую там, а затем переместу ссылки, в /src/refsкоторые проект их берет.

Моя проблема в том, что у меня есть .gitignoreвозможность игнорировать *.dllи *.pdb. Я могу сделать, git add -f bar.dllчтобы форсировать добавление игнорируемого файла, это нормально, проблема в том, что я не могу понять, какие существуют файлы, которые игнорируются.

Я хочу перечислить пропущенные файлы, чтобы не забыть добавить их.

Я прочитал справочную страницу git ls-filesи не могу заставить ее работать. Мне кажется, что git ls-files --exclude-standard -iследует делать то, что я хочу. Что мне не хватает?

Эндрю Бернс
источник
12
В наши дни вы будете использовать не git-ls-files, а «git ls-files»
wojo
7
Я умоляю вас проверить правильность ответа riyad, поскольку он единственный, который признает, что нет гарантированного способа сделать это, используя только команды git (включая git cleanтрюк), как показано здесь . Кроме того, я рекомендую против примера «исключить из» в вашем резюме, так как он фактически не обращает внимания на любые файлы .gitignore. Я спрашиваю об этом особенно потому, что эта страница является лучшим ответом Google.
Александр Берд
Краткий обзор «Резюме того, что работает»: на странице справки «Git ls-files» объясняется, что «-i» означает включение исключенных файлов для вывода ls. У меня было то же недоразумение, пока я не прочитал «это медленно». ;-)
будет
2
Ответы должны идти в ответном сообщении, а не в редактировании вопроса.
Flimm
У меня есть git config --global alias.ls ls-files --exclude-standard, и это делает ответ на этот вопрос git ls -i.
до

Ответы:

663

Ноты:


Также интересно (упоминается в qwertymk «s ответ ), вы можете также использовать git check-ignore -vкоманду, по крайней мере на Unix ( не работает в CMD Windows , сессии)

git check-ignore *
git check-ignore -v *

Второй отображает фактическое правило, .gitignoreпозволяющее игнорировать файл в вашем git-репо.
В Unix, используя « Что распространяется на все файлы в текущем каталоге рекурсивно? » И bash4 +:

git check-ignore **/*

(или find -execкоманда)

Примечание: https://stackoverflow.com/users/351947/Rafi Б. предлагает в комментариях , чтобы избежать (рискованный) globstar :

git check-ignore -v $(find . -type f -print)

Не забудьте исключить файлы из .git/подпапки.


Оригинальный ответ 42009)

git ls-files -i

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

if (show_ignored && !exc_given) {
                fprintf(stderr, "%s: --ignored needs some exclude pattern\n",
                        argv[0]);

exc_given ?

Оказывается, после -iфактического списка нужен еще один параметр :

Пытаться:

git ls-files -i --exclude-from=[Path_To_Your_Global].gitignore

(но это будет только список вашего кэшированного (не игнорируемого) объекта с фильтром, так что это не совсем то, что вы хотите)


Пример:

$ cat .git/ignore
# ignore objects and archives, anywhere in the tree.
*.[oa]
$ cat Documentation/.gitignore
# ignore generated html files,
*.html
# except foo.html which is maintained by hand
!foo.html
$ git ls-files --ignored \
    --exclude='Documentation/*.[0-9]' \
    --exclude-from=.git/ignore \
    --exclude-per-directory=.gitignore

На самом деле, в моем файле 'gitignore' (называемом 'exclude') я нахожу командную строку, которая может вам помочь:

F:\prog\git\test\.git\info>type exclude
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

Так....

git ls-files --others --ignored --exclude-from=.git/info/exclude
git ls-files -o -i --exclude-from=.git/info/exclude

git ls-files --others --ignored --exclude-standard
git ls-files -o -i --exclude-standard

должен сделать свое дело.

Как упомянуто на справочной странице ls-files , --othersэто важная часть, чтобы показать вам не кешированные, не зафиксированные, обычно игнорируемые файлы.

--exclude_standardэто не просто ярлык, а способ включить все стандартные настройки «игнорируемых шаблонов».

exclude-standard
Добавить стандартные GIT исключения: .git/info/exclude, .gitignoreв каждом каталоге, и user's global exclusion file.

VonC
источник
@ VocC, исходя из моего понимания этих тестов , ответ, который вы рекомендуете сверху, может иметь большие недостатки. Вот почему я обычно рекомендую вместо этого ответ Риада .
Александр Берд
2
Начиная с выпуска Git v2.13.2: git status --ignoredкажется, он также показывает неотслеживаемые файлы: github.com/git/git/blob/master/Documentation/RelNotes/…
Пау
1
вау, git check-ignore -v *прекрасно работает, так как показывает, где применяется конфиг. Спасибо.
Хоанг Тран
@MikeD Чтобы заставить * / работать (или на самом деле, вы можете просто сделать **), вам нужно установить globstar, shopt -s globstarпосле чего он должен работать.
Вед
Без включения (рискованный) globstar:git check-ignore -v $(find . -type f -print)
Рафи
484

Есть гораздо более простой способ сделать это (git 1.7.6+):

git status --ignored

См. Есть ли способ сообщить git-status, чтобы он игнорировал эффекты файлов .gitignore?

Пенге Гэн
источник
3
Какую версию Git вы используете? Мой (1.7.0.4) говорит error: unknown option 'ignored'. Даже добавление, -sкак предлагается в связанном посте, не работает.
Александр Берд
3
Моя версия 1.7.6. Требуется еще одна версия 1.7.5.1 -s. Вы можете попытаться git status -hузнать, --ignoredподдерживается ли это
Penghe Geng
1
Я думаю, это просто еще не поддерживается в 1.7.0.4. На моем другом компьютере установлен 1.7.9, а флаг --ignored есть
Alexander Bird
4
Я попробовал каждое решение на этой странице. Это самый лучший. Он показывает как файлы, так и каталоги. Эта функция, вероятно, была недоступна, когда этот вопрос был задан изначально. (Между прочим, все решения не будут работать должным образом с новым «git init», пока вы не
внесете
12
Это, безусловно, намного лучше, чем принятый ответ. Это также намного безопаснее, чем git clean -ndXрешение, потому что редкая ситуация, когда кто-то по ошибке забывает флаги, будет иметь безвозвратный эффект на хранилище, так как неотслеживаемые файлы удаляются. Так что это опасно. Напротив, git status --ignoredэто всегда безопасно, даже когда ошибочно напечатано, и это естественно запомнить.
Иоаннис Филиппидис
400

Другой вариант, который довольно чистый (без каламбура):

git clean -ndX

Объяснение:

$ git help clean

git-clean - Remove untracked files from the working tree
-n, --dry-run - Don't actually remove anything, just show what would be done.
-d - Remove untracked directories in addition to untracked files.
-X - Remove only files ignored by Git.

Примечание. В этом решении не отображаются проигнорированные файлы, которые уже были удалены.

ma11hew28
источник
Отлично ... однако причина, по которой я задал исходный вопрос, заключалась в том, чтобы я мог убедиться, что файлы вендора (* .dll), которые должны были там быть ..., поэтому их удаление не будет желаемым результатом. ОДНАКО: это хорошо знать, так как я изменил свою стратегию с игнорирования * .dll на игнорирование моей выходной папки сборки (но не папок моего поставщика). Это было бы хорошей альтернативой make cleanи очень полезно на сервере сборки.
Эндрю Бернс
2
Я использую git версии 1.7.0.4, и две команды ('git ls-files -o -i --exclude-standard', 'git clean -dXn') не эквивалентны. Первый покажет мне 4 файла, а второй только два. (.gitignore ~, index.php ~, sql / create_users.sql ~, www / index.php ~) (удаляет .gitignore ~, удаляет index.php ~). Я скучаю по чему-то здесь?
Сезар
@VonC, милый! Спасибо! @ Цезарь, я не уверен. Я не очень знаком с git ls-files -o -i --exclude-standard. git clean -dXnвсегда был тем, что я хотел, но не показывает проигнорированные файлы, которые уже были удалены. git ls-files -o -i --exclude-standardможет сделать это. Так что это может быть причиной разницы.
ma11hew28
3
Одна крошечная вещь - возможно, будет хорошей идеей ввести nпервый, меньший шанс случайного удаления таким образом; git clean -ndX
Тобиас Коэн
1
@TobiasCohen приятно! Я обновил ответ с вашим предложением. Это безопаснее. Хотя, если вы пропустите nGit по умолчанию fatal: clean.requireForce defaults to true and neither -n nor -f given; refusing to clean. Все еще довольно безопасно, но печатать nпервое еще безопаснее! :)
ma11hew28
39

Хотя в целом правильное ваше решение не работает при любых обстоятельствах. Предположим, что каталог репо выглядит так:

# ls **/*                                                                                                       
doc/index.html  README.txt  tmp/dir0/file0  tmp/file1  tmp/file2

doc:
index.html

tmp:
dir0  file1  file2

tmp/dir0:
file0

и .gitignore, как это:

# cat .gitignore
doc
tmp/*

Это игнорирует docкаталог и все файлы ниже tmp. Git работает как положено, но данная команда для вывода списка игнорируемых файлов - нет. Давайте посмотрим, что говорит Git:

# git ls-files --others --ignored --exclude-standard                                                            
tmp/file1
tmp/file2

Обратите внимание, что docотсутствует в списке. Вы можете получить это с:

# git ls-files --others --ignored --exclude-standard --directory                                                
doc/

Обратите внимание на дополнительную --directoryопцию.

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

Riyad
источник
2
Это дало мне то, что я хотел, в то время как другие не (для моего конкретного случая) ... спасибо! Очень неприятно запускать две команды, но с игнорируемым каталогом опция --directory, по крайней мере, находит меня, и я могу передать это в команду find, чтобы найти файлы. Спасибо!
Линдес
Это делает все это сразу и расширяет каталоги:(git ls-files -oi --exclude-standard; git ls-files -oi --exclude-standard --directory) | perl -nle '$seen{$_}++||next;if(-d){system"find",$_,"-type","f"}else{print}'
Ди Ньюкум
17

Git теперь имеет встроенную функциональность

git check-ignore *

Конечно, вы можете изменить глобус на что-то, как **/*.dllв вашем случае

Git Reference

qwertymk
источник
7
git check-ignore **/*включить файлы в подкаталоги
mzimmer
это только перечисляет директории верхнего уровня.
Radon8472
13

Должно быть достаточно использовать

git ls-files --others -i --exclude-standard

поскольку это охватывает все, что покрыто

git ls-files --others -i --exclude-from=.git/info/exclude

следовательно, последнее является излишним.


Вы можете сделать это проще, добавив псевдоним в свой ~/.gitconfigфайл:

git config --global alias.ignored "ls-files --others -i --exclude-standard"

Теперь вы можете просто напечатать, git ignoredчтобы увидеть список. Намного легче запомнить и быстрее набирать текст.

Если вы предпочитаете более сжатое отображение решения Джейсона Гена, вы можете добавить псевдоним для этого, например:

git config --global alias.ignored "status --ignored -s"

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

git ignored | grep some-file-that-isnt-being-ignored-properly

Затем, когда вы просто хотите увидеть короткий дисплей, его достаточно легко запомнить и напечатать

git status --ignored

( -sОбычно это можно отключить.)

иконоборец
источник
Это никогда не работало для меня, потому что вы должны вручную перечислить эти файлы. git status --ignoredработает над Debian sid, но может быть очень новым… но, видимо, он был добавлен из-за
широкого
1
Под «работает на Debian sid» я предполагаю, что вы имеете в виду «работает с версией Git, установленной по умолчанию на Debian sid»? Вы действительно должны избегать возможности быть заложниками версий утилит, включенных в ваш дистрибутив. Вы можете обновить их независимо от самого дистрибутива.
иконоборчество
12

Вот как напечатать полный список файлов в рабочем дереве, которые соответствуют шаблонам, расположенным в любом месте в нескольких источниках Gitignore Git (если вы используете GNU find):

$ cd {your project directory}
$ find . -path ./.git -prune -o -print \
| git check-ignore --no-index --stdin --verbose

Он проверит все файлы в текущей ветви репозитория (если вы не удалили их локально).

И это также идентифицирует конкретные исходные строки gitignore.

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

Отрицательные образцы gitignore также подобраны. Тем не менее, они легко различимы в списке, потому что они начинаются с !.

Если вы используете Windows, Git Bash включает GNU find(как показано find --version).

Если список длинный (и у вас есть rev), вы можете отобразить их также по расширению (несколько):

$ cd {your project directory}
$ find . -path ./.git -prune -o -print \
| git check-ignore --no-index --stdin --verbose \
| rev | sort | rev

Для более подробной информации, см man find, man git-check-ignore, man rev, и man sort.

Смысл всего этого подхода в том, что Git (программное обеспечение) быстро меняется и является очень сложным. В отличие от проекта GNU findявляется чрезвычайно стабильной (по крайней мере, в его функции используется здесь). Таким образом, любой, кто хочет быть конкурентоспособным, демонстрируя свои глубокие знания Git, ответит на вопрос по-другому.

Какой лучший ответ? Этот ответ намеренно сводит к минимуму зависимость от знаний Git для достижения цели стабильности и простоты с помощью модульности (информационной изоляции) и рассчитан на длительное использование.

MarkDBlackwell
источник
Большое спасибо! Я изо всех сил пытался выяснить, почему некоторые из моих новых исходных файлов иногда отсутствовали в моих коммитах. Оказывается, у меня был шаблон: bin *, который, как я думал, будет соответствовать только именам файлов / каталогов, начинающимся с bin, но вместо этого он сопоставляет все, что включает bin, в полный путь к файлу / каталогу! Полагаю, моя проблема связана с неправильным пониманием точной семантики сопоставления с образцом в .gitignore. Ваш двухстрочный скрипт помог мне найти эту ошибку!
Николя Рокет
1

(расширяя другие ответы)

Обратите внимание, git check-ignoreиспользует совершенное, .gitignoreа не одно в вашем рабочем дереве! Чтобы поиграть с ним, не загрязняя свою историю git, вы можете свободно попробовать отредактировать его, а затем зафиксировать с помощью git commit --amend.

Эта проблема возникает, в основном, если вам нужен обходной путь, когда git не следует каталогам. Введите в .gitignore:

dirtokeep/**
!dirtokeep/.keep

.keepдолжен быть файл нулевой длины в dirtokeep.

Результатом будет то, что все в dirtokeepбудет игнорироваться, кроме dirtokeep/.keep , что приведет к тому, что dirtokeepкаталог будет построен на clone / checkout.

Петер - Восстановить Монику
источник
0

Если есть несколько игнорируемых каталогов, почему бы не использовать «git status node / logs /», который скажет вам, какие файлы нужно добавить? В каталоге у меня есть текстовый файл, который не является частью вывода статуса, например:

На главном филиале
Ваша ветвь обновлена ​​с «origin / master».
Не отслеживаемые файлы:
(используйте «git add ...» для включения в то, что будет зафиксировано)

    node/logs/.gitignore 

.gitignore это:

*

! .gitignore

pikknz
источник