Влияние редактирования истории мерзавцев - PullRequest
0 голосов
/ 07 декабря 2018

У нас довольно плохая ситуация с состоянием одного из наших репозиториев.Кто-то небрежно выделил 4 ГБ бинарных файлов в репозиторий и отправил его на удаленный мастер.Затем они сказали "Ой!"и отменил этот коммит.

К сожалению, git хранит только diff, и, поскольку он не может действительно хранить diff двоичных файлов, он сохраняет весь файл в истории.И поскольку он был включен в историю дважды (один раз, когда он был добавлен, один раз, когда он был удален), размер репо теперь составляет 8 ГБ.Это вызывает у нас огромные проблемы и заставляет наши сборки занимать на час больше времени, чем им нужно.

Я понимаю, что могу использовать такие инструменты, как rebase и filter-branch, чтобы удалить эти коммиты или удалить эти файлы из истории git.Тем не менее, каждая публикация или документация по этим инструментам гласит: «Если коммиты, которые вы хотите отредактировать, уже отправлены на удаленный компьютер, то НЕ ДЕЛАЙТЕ ЭТО! История перезаписи - ПЛОХАЯ ИДЕЯ !!!»

Но нигде фактически не объясняется, каково влияние переписывания истории.У нас действительно нет выбора - мы ДОЛЖНЫ удалить эти файлы из истории.Но, учитывая все страшные предупреждения об опасностях переписывания истории git, мы очень боимся на самом деле пытаться удалить эти файлы.

Итак, я надеюсь, что полезный пользователь StackOverflow сможет объяснить, что может быть результатом удаления этих огромных файлов с помощью filter-branch, или, может быть, если есть какое-то лучшее решение, о котором мы не знаем.

1 Ответ

0 голосов
/ 07 декабря 2018

Это распространенное заблуждение, что git хранит различия.Он на самом деле хранит полное содержимое каждой версии *.На самом деле, вся модель git построена вокруг гарантированного безупречного извлечения исходного кода, чего просто не могут добиться VCS на основе diff.

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

Для ответа на ваш основной вопрос.

Git хранит данные как набор объектов, которые ссылаются надруг с другом.(См. Деревья Меркле ). Поскольку деревья и история построены из объектов, которые ссылаются на другие объекты, очень трудно действительно удалить общие данные из репозитория git.

"Переписывание истории"это даже немного неправильно, поскольку git никогда не переписывает историю, он просто возвращается и создает новую историю, а затем указывает на эту новую историю.Старые вещи могут зависать месяцами перед сборкой мусора.Как только вы начинаете делиться этим, в логической модели git ваша переписанная история - это просто еще одна ветвь в другом экземпляре репо.

Обычно ветки перемещают кодовую базу вперед и могут быть объединены для получения этой истории.все вместе.Если у вас есть ветвь функций с именем feature1 и слияние ее с веткой master, это не только код, который становится частью мастера, все коммиты на feature1 также становятся частью мастера.Когда каждая ветвь представляет собой отдельный фрагмент кода, это не проблема.

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...