Понимание маскировки.gitignore и git clean
Мне действительно трудно понять, как работает файл.gitignore...
Вот как выглядит мой файл:
custom/history
cache
*.log
custom/modules/*/Ext
upload
sugar-cron*
custom/application/Ext
custom/Extenstion/modules/*/Ext/Language
!custom/modules/*/Language/cs_CZ.*
!custom/modules/*/Language/en_us.*
custom/Extenstion/application/Ext/Language
!custom/Extenstion/application/Ext/Language/cs_CZ.*
!custom/Extenstion/application/Ext/Language/en_US.*
.htaccess
config.php
config_override.php
files.md5
Вот как выглядел мой git-статус:
apache@cb772759c68a sugarcrm$ git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# LOG.txt
# deploy_backup/
nothing added to commit but untracked files present (use "git add" to track)
Итак, теперь я хотел избавиться от двух неотслеживаемых файлов, но, к моему удивлению, была также удалена целая куча других файлов.
apache@cb772759c68a sugarcrm$ git clean -fd
Removing Disabled/upload:/
Removing LOG.txt
Removing custom/Extension/modules/Bugs/Ext/Language/
Removing custom/Extension/modules/Cases/Ext/Language/
Removing custom/Extension/modules/EmailAddresses/
Removing custom/Extension/modules/EmailParticipants/
Removing custom/Extension/modules/ForecastManagerWorksheets/
Removing custom/Extension/modules/ForecastWorksheets/
Removing custom/Extension/modules/Forecasts/
Removing custom/Extension/modules/Meetings/Ext/Layoutdefs/
Removing custom/Extension/modules/Meetings/Ext/WirelessLayoutdefs/
Removing custom/Extension/modules/Meetings/Ext/clients/
Removing custom/Extension/modules/ModuleBuilder/
Removing custom/Extension/modules/OutboundEmail/
Removing custom/Extension/modules/PdfManager/
Removing custom/Extension/modules/ProjectTask/Ext/Language/
Removing custom/Extension/modules/Quotas/
Removing custom/Extension/modules/Quotes/Ext/Dependencies/
Removing custom/Extension/modules/Targets/
Removing custom/Extension/modules/Tasks/Ext/Language/
Removing custom/Extension/modules/TimePeriods/
Removing custom/application/
Removing custom/install/
Removing custom/modules/Administration/
Removing custom/modules/Bugs/
Removing custom/modules/Cases/
Removing custom/modules/Contracts/
Removing custom/modules/Emails/
Removing custom/modules/HHP_Products/
Removing custom/modules/KBContents/
Removing custom/modules/Project/
Removing custom/modules/ProjectTask/
Removing custom/modules/ProspectLists/
Removing custom/modules/Prospects/
Removing custom/modules/Quotas/
Removing custom/modules/Reports/
Removing custom/modules/RevenueLineItems/
Removing custom/modules/Schedulers/
Removing custom/modules/Tags/
Removing custom/modules/Teams/
Removing custom/modules/hhp_assignment_zip/
Removing custom/modules/hhp_zipcode/
Removing custom/working/modules/Calls/
Removing custom/working/modules/Leads/clients/
Removing deploy_backup/
Removing deploy_log/
Removing dist/identity-provider/tests/docker/saml-test/config/simplesamlphp/config/
Removing vendor/sugarcrm/identity-provider/tests/docker/saml-test/config/simplesamlphp/config/
Первый пункт - удаленные файлы не были показаны после git status
так очевидно, что они были частью "маски" gitignore... Кто-нибудь может объяснить, как любой из этих файлов соответствует любому шаблону в gitignore? подобно vendor/sugarcrm/identity-provider/tests/docker/saml-test/config/simplesamlphp/config/
... Может кто-нибудь помочь мне с созданием пропитера gitignore?
Второй момент - я думал, что.gitignore "защищает" эти неверсированные файлы от git clean
тот мерзавец буквально не предпринимает никаких действий на них. Поэтому очевидно, что он действительно удаляет их... как я не могу удалить неверсированные файлы при использовании git clean
?
РЕДАКТИРОВАТЬ: я перепутал git clean с git rm, я все время говорил о git clean
РЕДАКТИРОВАТЬ 2: оказалось, что удаленные каталоги, которые не соответствуют.gitignore, были "пустыми" в конце концов. (у них были подкаталоги, но дерево каталогов было без каких-либо файлов...)
2 ответа
TL;DR
Вы неправильно поняли, что git clean
удаляет по умолчанию и с -d
, (Примечание: я не большой поклонник git clean
себя; слишком легко удалить драгоценные файлы.)
Долго
Как отмечает Phd, перечисление файла в .gitignore
специально отключает, по умолчанию, имея git clean
убери это прочь Тем не мение, git clean
(значительно) сложнее, чем это. Мы немного углубимся в это.
Во-первых, давайте рассмотрим одну особенность .gitignore
записей. Если вы уже знаете все это (но никто не знает:-)), вы можете перейти к git clean
конкретные разделы ниже.
Отслеживаемый файл (который сейчас находится в индексе) никогда не игнорируется, поэтому соответствие
.gitignore
или эквивалент (например,.git/info/exclude
) картина не имеет значения.Фраза в индексе прямо сейчас означает именно это. Когда вы используете
git add
или жеgit rm --cached
добавить или удалить файл, который изменяет его отслеживаемость. Вы также можете использоватьgit ls-files --stage
выгрузить полный список каждого файла в индексе вместе с его промежуточными данными - mode, hash и stage-slot-number - или без--stage
чтобы получить только имена.Файл (не каталог), который был найден Git и которого нет в индексе, не отслеживается. Git не хранит каталоги, поэтому каталоги никогда не появляются в индексе. 1 Отслеживаемый или неотслеживаемый является чисто свойством файлов.
Не отслеживаемый файл также может быть проигнорированным файлом. Если так,
git add
не добавит его, даже если вы укажете его явно в командной строке (хотя вы можете указать его явно и использовать--force
добавить это).Это означает, что файлы (но не каталоги) попадают в одну из трех категорий: отслеживаемые, неотслеживаемые (только) или неотслеживаемые и игнорируемые. Это важно для
git status
, который жалуется только на неотслеживаемые файлы (не отслеживаемые и игнорируемые), но и в момент дляgit clean
также.Наконец, когда Git выполняет полный поиск / сканирование дерева каталогов - как в
git add .
например - и обнаруживает каталог, который он может пропустить (не имеет отслеживаемых файлов внутри него), Git проверит, соответствует ли сам каталог.gitignore
шаблон, и если так, не заглядывайте внутрь. Это ускоряетgit status
а такжеgit add -A
/git add .
в таких каталогах (иногда очень много, если вы можете игнорировать, например, целое дерево поставщиков или SDK).
Правило 4: почему, если вы хотите не игнорировать определенные пути к файлам, которые находятся под каким-либо путем к каталогу, вы должны указать Git специально не игнорировать каталог. Если вы игнорируете каталог, Git может никогда не заглянуть внутрь каталога. Это влияет на эти три строки, в частности:
custom/Extenstion/application/Ext/Language
!custom/Extenstion/application/Ext/Language/cs_CZ.*
!custom/Extenstion/application/Ext/Language/en_US.*
Если вы проигнорировали весь каталог custom/Extenstion/application/Ext/Language
, Git не заглядывает внутрь и никогда не найдет подходящих файлов custom/Extenstion/application/Ext/Language/cs_CZ.*
игнорировать это. Поэтому необходимо исключить сам каталог из игнорируемого статуса: вы должны изменить первую строку, чтобы читать custom/Extenstion/application/Ext/Language/*
, так что Git должен заглянуть внутрь каталога. Последующие строки, заканчивающиеся на cs_CZ.*
а также en_US.*
переопределит игнорируемый статус для чешских и англо-американских файлов.
1 Фактически, они могут появляться в указателе, но только для того, чтобы их можно было рассматривать как особые случаи. git ls-files
, который может показать вам содержимое индекса, пропускает прямо над ними.
С помощью git clean -d
четко изменяет правило 4
Git может удалить каталог, только если он пуст. Это общее правило, поддерживаемое ОС: если каталог d
содержит несколько файлов d/f1
, d/f2
и так далее, и вы должны были удалить d
без удаления файлов у вас возникнут проблемы с файлами. Система заставляет вас сначала удалить файлы в каталоге. Это относится и к подкаталогам: вы не можете удалить d
если d/sub
существует, даже если d/sub
сам по себе пустой каталог. Только пустые каталоги могут быть удалены.
Бег git clean
без -d
не только оставляет правило 4 установленным, но фактически расширяет его. Например, в примере, с которого мы начали, Git замечает, что (1) custom/Extenstion/application/Ext/Language
это каталог; (2) каталог соответствует шаблону игнорирования; так (3) при условии, что нет файлов в custom/Extenstion/application/Ext/Language
которые уже отслежены, Git может и пропустит весь каталог (и, конечно, не удалит его, так как git clean
работает без -d
).
Предположим, что есть еще один каталог с именем xyzzy/
в списке нет файлов Этот каталог может быть полностью пустым. В этом случае в нем нет неотслеживаемых файлов по определению; так git clean
без -d
ничего не должен с этим делать. Или это могут быть файлы; эти файлы по определению не отслеживаются (и, следовательно, могут не отслеживаться и игнорироваться), но вы сказали не удалять каталоги, поэтому git clean
до сих пор даже не удосужился заглянуть внутрь. Это немного странный случай: Git часто не заглядывает в неизвестные каталоги. 2 (Вы видите это с git status
а также: вы должны использовать git status -uall
чтобы найти файлы внутри таинственного каталога. Но git add -A
или же git add .
должен заглянуть внутрь, если каталог не игнорируется, поэтому правило 4 немного сложнее в общем случае.)
Бег с -d
хотя, по-видимому, полностью исключает правило 4. Опять же, чтобы удалить каталог, Git должен сначала удалить все файлы в каталоге. Чтобы сделать это, Git также должен перечислить содержимое. Так что если вы скажете git clean
использовать -d
представляется целесообразным полностью отключить правило 4. Отсутствие каталога в имени пути заставит Git сканировать содержимое каталога. Либо нам уже нужно было заглянуть внутрь, потому что есть отслеживаемые файлы, либо нам нужно заглянуть внутрь, чтобы удалить файлы, чтобы удалить каталог.
2 Обратите внимание, что "неизвестный" - это не то же самое, что "неотслеживаемый". Это даже не термин Git; Я сделал это здесь. Однако, как мы увидим, было бы неплохо, если бы Git определил фразу "каталог без отслеживания".
Какие git clean
удаляет
Бег git clean -n
покажет вам, что он будет удалять. Этот показ использует некоторые сокращения: удаление каталога подразумевает удаление всех файлов в этом каталоге, включая (рекурсивно) подкаталоги с подфайлами. Это безопаснее, чем бегать с -f
вместо -n
, поскольку -f
показывает то, что он удалил, таким же образом -n
показывает, что это будет удалить.
По умолчанию, git clean
удаляет файлы, которые не отслеживаются, но не файлы, которые не отслеживаются и игнорируются. То есть вернитесь к пункту 3 выше и посмотрите на три классификации файлов: git clean
удаляет среднюю классификацию (только). Добавление -X
(верхний регистр X) говорит Git: не удаляйте файлы без отслеживания; вместо этого удалите неотслеживаемые и игнорируемые файлы.
Добавление -x
говорит Git: не читайте обычные файлы директив игнорирования, такие как .gitignore
, На этом этапе никакие файлы не будут игнорироваться, поэтому (независимо от того, какие файлы отслеживаются) никакие файлы не могут быть отслежены и проигнорированы. Сочетая это с -X
не имеет смысла, 3 так git clean
запрещает вам использовать оба -x
а также -X
,
Бег git clean
с -d
добавляет удаление пустого каталога. Здесь все становится особенно блекло, хотя. Кажется, что классификация отслеживаемых, не отслеживаемых и не отслеживаемых и игнорируемых Git немного нарушается. В документации сказано, что -d
будут:
Удалите неотслеживаемые каталоги в дополнение к неотслеживаемым файлам.
Но у Git нет определения неотслеживаемых каталогов. "Tracked-ness" является исключительно свойством файлов. В сноске мы увидели, что каталоги проникают в индекс как невидимые объекты (для ускорения различных операций Git), но это не означает, что каталоги отслеживаются.
Мы можем составить один: "неотслеживаемый каталог" может быть каталогом, который не содержит отслеживаемых файлов. Я думаю (но не доказал, к моему собственному удовлетворению), что это определение работает и объясняет git clean
Поведение Тем не менее, было бы очень полезно, если бы документация Git действительно определила это правильно.
3 Объединение -x
а также -X
с -e
может иметь практическое применение, но Git все еще запрещает это, по крайней мере, на сегодняшний день.
.gitignore
игнорирует файл от добавления и подтверждения. Это не защищает их от очистки, как раз наоборот.Эти очищенные файлы связаны с
.gitignore
следующим образом:custom / Расширение / модули / Ошибки /Ext/ Язык /Custom / Расширение / Модули / Случаи /Ext/ Язык /
матч custom/modules/*/Ext
править.
LOG.txt
vendor/sugarcrm/identity-provider/tests/docker/saml-test/config/simplesamlphp/config/
Файлы не были добавлены в индекс, поэтому они могут быть очищены.
- Чтобы избежать очистки неверсированных файлов, не запускайте
git clean
, Удалите ненужные файлы вручную.