BFG Repo Cleaner — альтернатива свежему клону

Я собирался спросить об этом в репозитории, но SO показался мне более подходящим местом, чтобы спросить об этом.

Я смог использовать BFG Repo Cleaner (отличный инструмент, спасибо!), чтобы уменьшить размер нашей папки .git более чем на 1 ГБ, что является ошеломляющим успехом для нашего хранилища. Я еще не отправил свой голый клон на удаленный доступ, так как я заинтересован в том, чтобы внести эти изменения, прежде чем понять последствия нажатия, а затем отказа от повторного клонирования.

Я понимаю, что передовая практика диктует, что, когда история изменилась таким образом, лучшим решением будет выполнить новое клонирование. Тем не менее, я работаю с командой из более чем 50 человек в репозитории объемом более 2 ГБ и 23 тыс. коммитов, и координация между командами может быть невероятно сложной в нашей структуре. В связи с этим у меня есть несколько вопросов:

  1. Каковы будут последствия, если я отправлю эти измененные ссылки, а люди будут использовать свою существующую копию, а не создавать новый клон?
  2. Нужно ли им делать что-то еще, чтобы смягчить эти последствия в рамках или в дополнение к их привлекательности, если это возможно?
  3. Изменится ли эта рекомендация вообще, если учесть, что удаленные BLOB-объекты относятся к истории, которой не менее года и не более трех лет?
  4. Наконец, учитывая, что новый клон не будет включать в себя любую работу, не синхронизированную с исходным потоком, есть ли у вас рекомендации по наилучшему способу переноса неотслеживаемых ветвей из одного клона в другой? Если для этого уже существует команда Git, я был бы рад услышать ваше мнение.

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


person metc500    schedule 21.03.2018    source источник
comment
Добро пожаловать в переполнение стека. Ваш вопрос не совсем подходит для этого места. Здесь вы должны задавать вопросы о конкретных проблемах кодирования программного обеспечения, публикуя минимально воспроизводимый пример, чтобы люди могли помочь вам преодолеть блокпост. Вопросы, основанные на мнении, осуждаются.   -  person Alan    schedule 21.03.2018
comment
Я бы не согласился на том основании, что репозиторий этого проекта направил меня в Stack Overflow, если я задаю общие вопросы. Цитата, "If you just have a general question, or there's something you don't understand, ask on stackoverflow.com (tag it with git-rewrite-history and bfg-repo-cleaner so I see it) - there are many more people who can answer that sort of question on Stackoverflow, you stand a good chance of getting your question answered quicker!" См. также: github.com/rtyley/bfg- repo-cleaner/blob/master/CONTRIBUTING.md   -  person metc500    schedule 21.03.2018
comment
@ Алан, мне это не кажется вопросом, основанным на мнении? Этот вопрос спрашивает, каковы последствия для возможного процесса очистки истории Git — это очень похоже на многие другие вопросы, связанные с git на SO, которые «как мне использовать этот инструмент?» / «Я использовал этот инструмент и не не понимаю, что произошло». Есть ли лучший сайт обмена стеками для вопросов, связанных с Git?   -  person Roberto Tyley    schedule 21.03.2018
comment
@roberto, мои извинения, metc500 - я неправильно понял вопрос. Я согласен с вами обоими и снимаю свои замечания.   -  person Alan    schedule 22.03.2018


Ответы (1)


Предисловие

Прежде чем мы углубимся в это, позвольте мне пояснить рекомендуемый процесс очистки истории Git в контексте активной команды разработчиков (независимо от того, какая технология используется для очистки — BFG Repo-Cleaner или git filter-branch):

  1. Попрактикуйтесь в выполнении очистки несколько раз на локальной одноразовой копии вашего репозитория, чтобы вы были уверены, что сможете это сделать и получите желаемый результат, и знаете, сколько времени это займет.
  2. COMMUNICATE WITH YOUR TEAM. This is essential, unavoidable (because Git is specifically built to complain and get in the way if history is rewritten) and just good practice for any team :-) You need to tell them:
    • Why the clean is happening (eg smaller repo!)
    • Когда планируется уборка, заранее предупредите их об этом.
    • Чтобы отправить всю свою работу в основной репозиторий до начала очистки — ее не нужно объединять с основной веткой, но вся работа должна быть включена. толкнул вверх на той или иной ветке.
    • Сообщите им, что им нужно будет удалить свои старые копии репозитория, когда очистка будет завершена, и повторно клонировать только что очищенный репозиторий.
  3. Когда вся работа будет перенесена в основной репозиторий, выполните зеркальный клон основного репозитория. . СДЕЛАЙТЕ БЭКАП ЭТОГО КЛОНА, чтобы всегда можно было вернуться, если что-то пойдет не так.
  4. Запустите очистку (с помощью BFG Repo-Cleaner или более медленного инструмента, такого как git filter-branch), и используйте git gc для обрезки мертвых объектов.
  5. Как только вы убедитесь, что очистка прошла успешно, отправьте очищенную историю обратно в основное хранилище (поскольку это был клон mirror, все старые ветки/теги будут перезаписаны новой очищенной историей)
  6. Сообщите своей команде, что пришло время удалить их старые копии репозитория и повторно клонировать очищенный репозиторий.

Итак, на ваши вопросы:

Что делать, если пользователь со старым репозиторием извлекает данные из очищенного репозитория?

Каковы будут последствия, если я отправлю эти измененные ссылки, а люди будут использовать свою существующую копию, а не создавать новый клон?

Плохо. По опыту могу сказать, что будет беспорядок, и люди будут запутаны и расстроены.

В частности, то, что происходит на машине этого человека, заключается в том, что команда git pull объединяет старую грязную историю и новую очищенную историю с двумя длинными расходящимися историями (изначально расходящимися с первой «грязной» фиксацией в вашей истории, которая в вашем случае была 3 года назад) были объединены одним совершенно новым и очень запутанным коммитом слияния. Пользователям редко бывает ясно, что это произошло — большинство визуализаторов журналов Git не визуализируют это таким образом, чтобы сделать это очевидным — если вам повезет, пользователь может сказать что-то вроде «У меня есть две копии каждого совершить сейчас, WTF?!" - но только если они действительно наблюдательны.

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

При планировании есть ли способ позволить пользователям сохранить свое старое репо, но обновить его, чтобы иметь очищенную историю?

Нужно ли им делать что-то еще, чтобы смягчить эти последствия в рамках или в дополнение к их привлекательности, если это возможно?

Технически, да. На практике процедура сложна, подвержена ошибкам, и если хотя бы один пользователь ошибается, вы, как и раньше, облажались.

На данный момент мы должны выяснить, почему вы пытаетесь уклониться от этой процедуры. Это потому что:

  • Вы пытаетесь избавить пользователей от необходимости знать и иметь дело с историей изменений Git? Похоже, это может быть вашей целью, основываясь на ваших высказываниях "координация между командами может быть невероятно сложно в нашей структуре" - но, к сожалению, это недостижимая цель, потому что Git не позволит вам изменить историю так, чтобы пользователи не заметили. Пользователям придется что-то сделать, и они должны согласовать свои действия с вами.
  • Вы хотите сократить время загрузки при создании нового клона вашего действительно огромного репозитория, надеясь, что Git загрузит только измененные большие двоичные объекты, а не все, что не изменилось?< /em> Это немного более разумная цель для гигантских многогигабайтных репозиториев, загрузка которых занимает несколько часов (хотя, если вы используете BFG, чтобы сделать репо намного меньше, мотивации меньше) - к сожалению, из-за деталей протокола Git. вы не сможете воспользоваться этими преимуществами. Протокол Git предназначен для определения того, какие коммиты находятся на удаленном сервере, которых нет в вашем локальном репозитории, и отправки адаптированного файла пакета, содержащего только то, что вам нужно для обновления вашего локального репо. Это здорово, но обратите внимание, что единицей сравнения является фиксация. Когда вы переписываете историю, дерево файлов коммитов практически не меняется, но идентификаторы коммитов все меняются, потому что идентификатор коммита является хэшем его родительского history, а также содержимое файлового дерева. Протокол Git сравнивает только идентификаторы коммитов, и все они разные, поэтому будут отправлены все коммиты, вместе с их объектами файлового дерева. Протокол не копает достаточно глубоко, чтобы понять, что ему не нужно отправлять большую часть этих объектов файлового дерева, и поэтому вы не получаете выгоду от того, что их копии уже есть в вашем локальном репо.

Имеет ли значение, как давно плохие вещи были в истории?

Изменится ли эта рекомендация вообще, если учесть, что удаленные BLOB-объекты относятся к истории, которой не менее года и не более трех лет?

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

Если плохие вещи были совершены много лет назад, то они есть у всех, и их всех нужно дезинфицировать.

Как насчет случайных коммитов/ветвей, которые не были перемещены в основной репозиторий при его очистке?

Наконец, учитывая, что новый клон не будет включать в себя любую работу, не синхронизированную с исходным потоком, есть ли у вас рекомендации по наилучшему способу переноса неотслеживаемых ветвей из одного клона в другой?

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

Если кто-то этого не сделает, он может попробовать перебазировать интересующие его ветки на очищенную историю. Для каждой ветки feature что-то вроде:

$ git rebase --onto clean-origin/feature unclean-origin/feature feature

...(что примерно переводится как "взять все коммиты, которые есть в моей функциональной ветке, которые я не отправил в основной репозиторий до того, как он был очищен, и воспроизвести их поверх основного очищенная версия репо этой ветки).

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

Вывод

Вы знаете свою команду, уверены ли вы, что все они могут безукоризненно выполнять эзотерические операции перезагрузки Git? И какая польза, если они это сделают? После того, как все сказано и сделано, не проще ли просто сказать им, чтобы они удалили свое старое репо и повторно клонировали?

person Roberto Tyley    schedule 24.03.2018
comment
Отличный обзор, и спасибо за акцент на социальных/командных аспектах общения! - person Jules Kerssemakers; 03.08.2018