1

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

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

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

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

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

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

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

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

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

1 ответ1

1

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

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

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

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

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

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

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

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

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

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

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .