Проверка целостности метаданных Git?

569
Wanderer

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

  • Два рабочих репозитория, называемые x иy
  • Пустое хранилище, называемое xy.git

Итак, изначально xи yподталкиваем и вытягиваем x.gitи все работает просто отлично. Теперь, скажем, один из объектов метаданных (.git/objects/... ) в x.gitпо какой-либо причине поврежден (выберите ваш любимый случайный случай).

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

Теперь я подумал, что это не так уж и плохо, потому что благодаря архитектуре git я могу просто сбросить пустой репозиторий в худшем случае и воссоздать его со всей историей из одного из моих рабочих наборов. Но нет. Без какого-либо уведомления испорченный файл пробирается через рабочие репозитории, что делает невозможным клонирование нового голого репозитория из них.

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

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

Кто-нибудь здесь хочет попробовать, если это воспроизводимо? Я экспериментировал с git-версией 2.7.4.

Любые советы о том, как противостоять такой коррупции, очень приветствуются.

1

1 ответ на вопрос

1
grawity

Я на самом деле предполагал, что что-то сломается при следующем толчке или толчке, но, к моему удивлению, все оказалось нормально. Больше коммитов, больше толкающих и тянущих, никаких проблем.

Каждый объект - файл, коммит и т. Д. - назван в соответствии с хеш-значением SHA1 его содержимого (плюс небольшой заголовок). Всякий раз, когда отдельный объект считывается в память для использования, данные хэшируются и сравниваются с именем объекта; любое несоответствие приведет к отображению ошибки.

Однако большинству операций не нужно читать весь репозиторий в память. В общем, все команды читают только необходимый минимум - конечно, вы бы заметили проблему, если бы попытались проверить битый коммит или diff против него, но такие операции, как создание коммита, вообще не заботятся о предыдущих объектах. Даже толкание требует небольшого выбора объектов (как дельта-база для «тонких» пакетов), потому что оба пира знают, что уже есть у другой стороны.

(Эта оптимизация является прямым результатом компоновки на основе снимка. Например, git add не нужно делать различий со старыми файлами, потому что он просто создает новый снимок по ходу работы. Затем git commit превращает этот снимок в коммит / Tree объекты, ничего не зная о предыдущем коммите, кроме его ID.)

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

Во-первых, имейте в виду, что клон с одним и тем же компьютером и той же файловой системой не упаковывает и не передает объекты - он просто жестко связывает файлы, чтобы сэкономить пространство и время. Вы должны явно отказаться от этого путем клонирования с file://URL-адреса вместо простого пути.

Однако клон по SSH или HTTPS (или вышеупомянутый файл: // URLs) фактически считывает и записывает данные объекта для создания пакета передачи, поэтому любой поврежденный объект, который должен был быть частью передачи , прервет процесс.

Если вам каким-то образом удастся отправить поврежденный объект на удаленный сервер - когда он проскальзывает через локальную упаковку и удаленную распаковку - это немного необычно (особенно после истории git.kde.org в 2013 году ), и я бы поднял эту проблему в списке рассылки Git.

(Не беспокойтесь, что в документации говорится об transfer.fsckObjectsотключении по умолчанию, - она ​​отключает только проверку структуры и синтаксиса объекта, а не проверку хеш-функции.)

Разве не должно быть чеков против этого где-нибудь?

Полная проверка может быть выполнена вручную с помощью git fsckкоманды. Это хорошая идея, чтобы cronjob это в ваших «центральных» хранилищах. Полная проверка не автоматизирована, потому что потребуется непомерное количество времени для повторной проверки полного репозитория при каждом коммите / push / pull / независимо от всех, кроме самых маленьких Git-репозиториев.

Частичная проверка неявно происходит всякий раз, когда мерзавец решает запустить git gc --autoпроцесс обслуживания фона. Это обслуживание считывает все недавно созданные «незакрепленные» объекты и архивирует их в файл .pack, поэтому проверка этих объектов производится бесплатно. (Однако вместо запуска по заданному расписанию он запускается всякий раз, когда у вас больше свободных объектов, чем установленный предел.)

Похожие вопросы