Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як об'єднати кілька репозиторіїв в один монорепозиторій зі збереженням історії?

Задача: є репозиторії api, admin і shared, і їх треба перенести в один репозиторій з каталогами apps/api, apps/admin, packages/shared - не втративши історію, щоб git log і blame працювали для старого коду.

Крок 1 - у кожному вихідному репозиторії перемістити файли в цільовий каталог через переписування історії (на свіжому клоні):

git clone https://github.com/acme/api.git api-rewrite
cd api-rewrite
git filter-repo --to-subdirectory-filter apps/api

Кожен коміт історії тепер виглядає так, ніби файли завжди лежали в apps/api. Без цього кроку git log -- apps/api/... і blame губили б історію на межі переміщення.

Крок 2 - злити переписані історії в новий репозиторій:

git init monorepo && cd monorepo
git commit --allow-empty -m "Initial monorepo commit"

git remote add api ../api-rewrite
git fetch api
git merge --allow-unrelated-histories --no-edit api/main

--allow-unrelated-histories потрібен, бо історії не мають спільного предка - без нього Git відмовляє: refusing to merge unrelated histories.

Повторити для admin і shared. Результат - коміт злиття, в якому сходяться всі історії.

Що ще врахувати:

  • теги конфліктують: v1.0.0 є в кожному репозиторії. Перейменувати при переписуванні: git filter-repo --tag-rename '':'api-' дає api-v1.0.0;
  • гілки в роботі: відкриті гілки теж треба перенести - переписати й відновити в монорепозиторії, або домовитися злити їх до міграції;
  • pull request і задачі посилаються на старі хеші й репозиторії - старі репозиторії архівувати (не видаляти), лишивши в README посилання на монорепозиторій;
  • CI, деплой, права, вебхуки налаштувати заново під каталоги;
  • залежності: якщо api підключав shared як Composer-пакет за версією - перейти на path-репозиторій, інакше в монорепозиторії залишаться дві копії коду;
  • .gitignore, .gitattributes, конфіги лінтерів з коренів репозиторіїв опиняться в підкаталогах - вирішити, що лишити локально, а що винести в корінь.

Порядок міграції: заморозити push у старі репозиторії, перенести, перевірити історію (git log --follow, blame на кількох файлах), перемкнути CI - і лише потім відкрити монорепозиторій для роботи.

Зворотна операція - виділення каталогу в окремий репозиторій - git filter-repo --subdirectory-filter packages/shared на свіжому клоні.

Докладніше в документації: git merge: --allow-unrelated-histories

Схожі питання