Split Git Репозиторий и хранить только историю оставшихся файлов - PullRequest
0 голосов
/ 06 апреля 2020

Я получил git репозиторий, содержащий 11 различных и независимых проектов (не спрашивайте меня, почему **** они все находятся в одном репозитории). Поскольку в некоторых проектах содержится много ресурсов, gitlab говорит, что размер репо составляет около 14,3 ГБ, что приводит к огромному времени проверки (в нашей системе CI / CD до 20 минут).

Поскольку мы только строим Один из проектов за один раз, я хочу разделить все проекты на разные репозитории. Поскольку Project A не нужны коммиты, связанные с файлами Project B, я хочу очистить всю историю.

Я уже пробовал разные способы:

  1. Удаление файлов. Файлы пропали, но все еще доступны через историю.
  2. Использование простого git filter-branch --prune-empty, но я хочу сохранить структуру файла.
  3. Использование git filter-branch --index-filter --prune-empty с git rm --cached --ignore-unmatch, но я все еще может восстановить старые файлы.
  4. Удаление файлов и использование Git BFG с --delete-folders. Отличный результат, но я могу предоставить только glob / regex и некоторые Projects, содержащие папки с именами других проектов (с плохими именами ...), которые также уничтожены ...

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

Пример структуры файла:

./
+- Project A/
+- Project B/
+- UI Projects/
|  +- Foo/
|  +- Bar/
+- Project E/
|  +- Foo/
|     +- Bar/
+- Build
   +- build_a/
   +- build_b/
   +- build_foo/
   +- build_bar/
   +- build_e/

Мои требования:

  • структура сохраненных файлов
  • хранить несколько путей (например, ./Project A/ и ./Build/build_a/ для Repo A)
  • история файлов, которые больше не являются частью новый репо уничтожен

Есть предложения?

Ответы [ 2 ]

1 голос
/ 06 апреля 2020

Следующий древовидный фильтр удовлетворяет вашим требованиям:

find . ./Build -maxdepth 1 -path . -o -path ./Build -o -path "./Project A" -o -path ./Build/build_a -o -exec rm -rf {} +

Замените Project A и build_a на фактическое имя проекта. Вы можете добавить другие пути, следуя примеру папки ./Build.

Передайте его в параметр --tree-filter filter-branch:

git filter-branch --tree-filter '...' --tag-name-filter cat --prune-empty -- --all
1 голос
/ 06 апреля 2020

Ну ... ты здесь упускаешь большую часть проблемы, но я вернусь к тому. Чтобы ответить на ваш вопрос, как задано:

Из опций, которые вы пробовали, filter-branch - это тот, который должен был сработать. (Имейте в виду, что git имеет новый инструмент, filter-repo, который они рекомендуют более filter-branch; но я не потратил время на переключение, и похоже, что у вас есть почти работающая процедура filter-branch в любом случае, поэтому я отвечу на ответ, используя filter-branch ...)

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

  • filter-branch создает набор «резервных ссылок» всякий раз, когда переписывает ссылки репо. Эти «резервные ссылки» все еще могут доходить до старой истории
  • . Перефлоги для ваших веток обеспечивают способ go вернуться туда, куда ранее указывали эти ветви; эти исторические записи рефлогов все еще могут доходить до старой истории

Самый простой способ избавиться от всего этого - отойти из репо, где вы проводили очистку. Если вы действительно хотите очистить его на месте, вам необходимо (1) удалить ссылки в пространстве имен original; (2) истечь или удалить reflogs - у меня всегда были проблемы с получением git, чтобы истечь их, но если все остальное терпит неудачу rm -r .git/logs; (3) запустить г c. Для этого типа операций я использую gc --force --aggressive --prune=now.

Теперь ... большая проблема, если история 11 проектов вместе составляет 14,3 ГБ, то история каждого проекта (в среднем) превышает 1 ГБ - и это все еще смешно. У вас есть более глубокая проблема. Разделение репозиториев, IMO, хорошая идея (я не фанат тренда "monorepo"); но вы также должны пытаться уменьшить общий размер репо.

Скорее всего, у вас есть большие двоичные файлы под контролем исходного кода. Очень редко это рекомендуется. Если вам нужно это сделать, вы должны использовать инструмент, такой как git lfs, чтобы сделать репо ядра небольшим и управляемым. Но если вы просто храните артефакты сборки, или зависимости, или что-то в этом роде, вам лучше будет заглянуть в хранилище артефактов (artifactory, nexus, ...). Для этого может потребоваться улучшенный инструментарий сборки для управления версиями зависимостей

...