laravel/framework - монорепозиторій: усі компоненти (src/Illuminate/Database, Support, Collections...) розвиваються в одному репозиторії з однією історією, одним набором тестів і однією системою CI.
Але користувачі можуть встановити окремий компонент - наприклад, Eloquent поза Laravel:
composer require illuminate/database
Пакети illuminate/* живуть в окремих репозиторіях лише для читання (github.com/illuminate/database), які автоматично отримуються з монорепозиторію розділенням історії (subtree split).
Як працює розділення:
Для каталогу src/Illuminate/Database інструмент проходить історію й будує нову історію, в якій:
- лишаються лише коміти, що змінювали цей каталог;
- файли зміщені в корінь (як
git filter-repo --subdirectory-filter); - результат детермінований: той самий вхід дає ті самі хеші, тож наступне розділення лише додає нові коміти, і push у репозиторій пакета - fast-forward.
SHA=$(splitsh-lite --prefix=src/Illuminate/Database)
git push git@github.com:illuminate/database.git "$SHA:refs/heads/13.x"
Вбудований git subtree split робить те саме, але на великій історії працює дуже повільно - тому Laravel, Symfony й інші використовують швидкий splitsh-lite, що кешує проміжні результати.
Процес у CI: після кожного push у гілку чи тегу монорепозиторію запускається розділення для кожного компонента й push у відповідні репозиторії - разом з тегами, щоб Packagist побачив нові версії.
Що потрібно для такої схеми:
composer.jsonу кожному компоненті з власними залежностями (illuminate/databaseзалежить відilluminate/support,illuminate/collections), а кореневийcomposer.jsonмонорепозиторію оголошуєreplaceдля всіх компонентів, щоб вони не встановлювалися двічі;- pull request лише в монорепозиторій: у репозиторіях пакетів pull request автоматично закриваються з поясненням, куди їх надсилати;
- узгоджене версіонування - усі компоненти отримують однаковий тег при релізі;
- межі між компонентами: залежності між каталогами мають відповідати оголошеним у
composer.json, інакше окремий пакет не працюватиме без решти фреймворку.
Для своїх проєктів схема корисна, якщо ви підтримуєте набір пов'язаних пакетів (SDK, модулі) - розробка й тестування разом, а публікація окремими пакетами. Для звичайного застосунку вона зайва.