2014-10-24 3 views
1

У меня есть репозиторий, который стал слишком большим до такой степени, что он стал непригодным для использования. В основном мой репозиторий более 2 ГБ и занимает слишком много времени для клонирования. Теперь я хочу сжать его, но все же смогу вернуться к некоторым старым версиям ... Сокращение будет связано с переписыванием истории, поэтому я прекрасно разбираюсь в этом. Люди с клонами должны будут переустанавливать/cherrypick/copyfiles поверх нового филиала в новом клоне репо.Как автоматически сквоить историю хранилища git, без конфликтов, чтобы сжать его?

  • У меня есть двоичные файлы в этом репозитории, но они мне нужны (подумайте об этом как обязательном ресурсе для запуска программного обеспечения). Поэтому я не могу использовать фильтр-ветвь или BFG для удаления больших двоичных файлов, так как может понадобиться их при возврате в прошлое.
  • Мне не нравятся предыдущие старые/уже объединенные ветки (пример: особенности ветвей), но мне небезразличны некоторые конкретные коммиты (например, главы прошлых релизов)
  • Так как я буду модифицировать (~ many ~) очень старые коммиты, я понятия не имею, как правильно решить проблемы с объединением конфликтов (как это может происходить с базовым rebase/cherrypick), поэтому я ищу решение, которое не создает конфликтов, или создает только конфликты, которые могут быть решены автоматически.
  • Я хочу сохранить все текущие ветви, поэтому люди, которые работают на клоне, могут переустанавливать/копировать на них.
  • Я хочу иметь соответствующую историю между моими новыми коммитами, чтобы соответствовать истории из старого репо (как будто коммиты были раздавлены). История последних ветвей начнется с одного из этих старых раздавленных коммитов.

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

  • клонировать зеркало существующего репо.
  • Создайте сиротские ветви из старых коммитов, которые я хочу сохранить. Это создаст беззастенчивые коммиты со всеми необходимыми в них файлами.
  • Как-то связать их, чтобы воссоздать старую историю репо => Как? слияние/переустановка/перезагрузка + фиксация сирот?
  • Черрипик каждого списка фиксации текущей ветви (с использованием интервалов) и применения их к последнему фиксации, который раздавил родительский элемент их первого расходящегося сообщения commit => Как автоматически найти, какой фиксации применить чередованный интервал фиксации вишни? Будет ли это работать без конфликтов?
  • Переместить теги на новое дерево. Удалите предыдущее дерево. git сбор мусора.

Возможно ли это выполнимо или выполнимо без каких-либо конфликтов? Будет ли это работать в любых случаях (git commit tree может быть довольно сложным)? Любое лучшее решение для безопасного и автоматического сквоша истории?

Мне кажется, что этот тип задачи обслуживания - это то, что произойдет для долгосрочного проекта, поэтому я предполагаю, что другие крупные проекты уже использовали какой-то тип решения. Но я предполагаю, что может быть вариант для git init (или другой команды), о котором я не знаю, для создания нового репо из старого репо для этой утилиты?

Обновление: Я нашел начало решения здесь: https://wincent.com/wiki/Editing,_amending,_or_squashing_the_root_commit_in_a_Git_repository Но я хотел бы сделать это несколько раз в моей истории, полностью автоматическим способом (т.е. без конфликтов) ...

+0

Вы уверены, что это фактически сократит историю? Если у вас есть большие двоичные файлы, шансы - это то, что занимает пространство, а не коммиты. Вы можете сбросить размер блоба для ваших больших объектов и посмотреть, какой процент от 2 ГБ они составляют, что даст вам какие-то улучшения, которых вы могли бы достичь. –

+0

После того, как коммиты раздавлены, двоичные файлы, на которые ссылались в этих фиксациях, больше не будут использоваться и могут быть собраны в мусор ... Я думаю. Спасибо за подсказку размера blob, это может быть полезно проверить. – Asmodehn

ответ

1

Вы можете клонировать только часть репо:

git clone --depth depth 

Это называется неглубокий клон.

Это было post on the Atlassian blog некоторое время назад, которое предлагает другие стратегии для работы с большим репо.

+0

Я нахожу мелкий клон полезным, только если вы хотите получить большой репозиторий как «только для чтения». В противном случае вам понадобится другой способ уменьшить фактическое репо. Не только ваш местный клон. – Asmodehn

0

Неглубокий клон Git - это один ответ, но с неглубокими клонами вы не можете нажать.

Насколько сквош обеспокоен сквош хорош только на неопубликованных историях, эта связь может быть полезным http://www.awanitech.com/git-squash.html

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

Если вы готовы сделать принудительный толчок (переписать историю); то вы можете выполнить фильтрацию и уменьшить размер.

Если ваши плохие версии находятся на совершенно другой ветке; вы можете создать пакет git и сделать его как сокращенный репозиторий.

+0

Мой репозиторий является приватным, и я могу сказать всем пользователям переупаковать, поэтому это не проблема. Но я хочу удалить коммиты, раздавленные впоследствии, так что неиспользуемые бинарные капли могут быть собраны в мусор. – Asmodehn

+0

Как вы сказали, ваш репозиторий локальный, создайте резервную копию существующего репозитория git. Сквош, используя метод, описанный в сопроводительной ссылке. Перейдите в другую папку и сделайте клон из вашего оригинального проекта, и он не будет иметь нежелательных коммитов.(конечно, создание другого клона сродни силовому толку) – forvaidya

+0

Спасибо, что решает первую часть моего вопроса, то есть сжимает старую историю. но тогда мне все равно нужно как-то связать недавнюю историю сверху, без конфликтов ... – Asmodehn

1

ИТАК через несколько дней проб и ошибок, вот это решение, которое я считаю, лучше всего:

1) С фиксацией вы хотите использовать в качестве нового корня, сделать checkout --orphan создать филиал сироту, и скопируйте измененные файлы для этой версии.

2) Для каждой фиксации C, которую вы хотите сохранить, checkout совершите C, reset для предыдущего нового фиксации B ', обязуйтесь совершить C' новое коммитирование с B 'в качестве родителя. (спасибо forvaidya за ссылку)

3) Теперь вам нужно пересоединить существующие ветви до последней фиксации, которую вы сохранили. Найдите эту фиксацию в старой истории. оттуда, перечислите все коммиты, у которых есть (или любой из его родителей) как прямой родитель. Затем вы можете использовать новый git replace --graft, чтобы заменить своего старого родителя новым фиксатором.

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

Предупреждение. Шаг 3) работает только в том случае, если вы используете git 2.X. Клиенты 1.X git не будут видеть изменения в графе фиксации.

+0

это действительно сократило ваше репо? –

+0

Так что да, это уменьшилось. Однако меньше, чем я ожидал ... мое репо было 2.0 ГБ раньше. С деревом 1,1 ГБ. После этой операции репо пошло на 1,6 ГБ. Большинство из них - файлы изображений размером> 2 МБ, но я не уверен в деталях того, что произошло в репозитории. Некоторые из моих пользователей находятся на окнах и не могут перейти в git 2.1, поэтому мне нужно просто создать новое репо с вершины существующей главной ветви. – Asmodehn

Смежные вопросы