СоХабр закрыт.

С 13.05.2019 изменения постов больше не отслеживаются, и новые посты не сохраняются.

H Монорепозитории: пожалуйста, не надо (часть 2) в черновиках

Всем привет!

Итак, новая порция обещанного холивара про монорепозитории. В первой части мы обсуждали перевод статьи уважаемого инженера из Lyft (и ранее Twitter) о том, какие есть недостатки у монорепозиториев и почему они нивелируют почти все достоинства этого подхода. Лично я во многом согласен с доводами, приведенными в оригинальной статье. Но, как и обещал, чтобы поставить точку в этом обсуждении, я бы хотел озвучить еще несколько моментов, на мой взгляд даже более важных и более практических.

Расскажу чуть-чуть о себе — я работал и в маленьких проектах, и в относительно больших, использовал полирепозитории в проекте с более 100 микросервисов (и SLA 99,999%). В данный момент занимаюсь переводом небольшого монорепозитория (на самом деле нет, всего лишь фронт js + бэкенд java) с maven на bazel. Не работал в Google, Facebook, Twitter, т.е. не имел удовольствия использовать правильно настроенный и обвешанный тулингом монорепозиторий.

Итак, для начала, что же такое монорепозиторий? Комментарии к переводу оригинальной статьи показали, что многие считают, что монорепозиторий, это когда все 5 разработчиков компании работают над одним репозиторием и хранят в нем фронтэнд и бэкенд вместе. Конечно же, это не так. Монорепозиторий, это способ хранения всех проектов компании, библиотек, инструментов для сборки, плагинов для IDE, скриптов деплоя и всего прочего в одном большом репозитории. Подробности здесь trunkbaseddevelopment.com.

Как же тогда называется подход, когда компания небольшая, и у нее просто нет такого количества проектов, модулей, компонентов? Это тоже монорепозиторий, только маленький.
Естественно, в оригинальной статье говорится о том, что все описанные проблемы начинают проявляться на определенном масштабе. Поэтому те, кто пишет, что их монорепозиторий на 1,5 землекопа отлично работает, конечно же абсолютно правы.

Итак, первый факт, который хотелось бы зафиксировать: монорепозиторий — это отличное начало для вашего нового проекта. Складывая весь код в одну кучку, на первых порах вы получите только одни преимущества, т.к. поддержка нескольких репозиториев безусловно добавит немного накладных расходов.

В чем же тогда проблема? А проблема, как было отмечено в оригинальной статье, начинается на определенном масштабе. И главное, не упустить момент, когда такой масштаб уже наступил.

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

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

Как же определить, что уже пора задумываться над тем, как оздоровить свой репозиторий? Конечно, это субъективный показатель, скорее всего ваши разработчики начнут жаловаться, что их что-то не устраивает. Но проблема в том, что может быть уже поздно что-то менять. Приведу некоторые цифры от себя лично: если клонирование вашего репозитория занимает больше 10 минут, если сборка проекта занимает более 20-30 минут, если количество разработчиков превышает 50 и так далее.

Интересный факт из личной практики:
я работал над довольно большим монолитом в команде из примерно 50 разработчиков, разделенных на несколько небольших команд. Разработка велась в фича-бранчах, а мердж происходил перед самым фича-фризом. Однажды я потратил на мердж нашей командной ветки 3 дня, после того как передо мной замерджились 6 других команд.

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

1) Время скачивания репозитория


С одной стороны, можно сказать, что это разовая операция, которую разработчик выполняет при начальной настройке своей рабочей станции. Лично у меня часто бывают ситуации, когда хочется склонировать проект в соседнюю папку, поковыряться в нем, а затем удалить. Однако, если клонирование занимает больше 10-20 минут, это сделать будет уже не так комфортно.

Но кроме того, не стоит забывать, что перед сборкой проекта на CI-сервере нужно клонировать репозиторий на каждого билд-агента. И вот тут вы начинаете придумывать, как же сэкономить это время, ведь если каждая сборка будет занимать на 10-20 минут дольше, а результат сборки появляться на 10-20 минут позже, это не устроит никого. Так репозиторий начинает появляться в образах виртуальных машин, из которых разворачиваются агенты, появляется дополнительная сложность и дополнительные расходы на поддержку этого решения.

2) Время сборки


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

Вариантов здесь не так уж и много — несмотря на то, что в тот же самый gradle были добавлены возможности кэширования (к сожалению, не использовал на практике), практической пользы они не приносят из-за того, что традиционные системы сборки не обладают повторяемостью результатов (reproducible builds). Т.е. из-за сайд-эффектов предыдущей сборки все равно в какой-то момент необходимо будет вызвать очистку кэшей (стандартный подход maven clean build). Поэтому остается только вариант использовать Bazel/Buck/Pants и иже с ними. Почему это не очень хорошо, обсудим чуть ниже.

3) Индексирование IDE


Мой текущий проект индексируется в Intellij IDEA от 30 до 40 минут. А ваш? Конечно можно открыть только часть проекта или исключить из индексирования все ненужные модули, но… Проблема в том, что переиндексирование происходит при каждом переключении с одной ветки на другую. Вот почему я люблю клонировать проект в соседнюю директорию. Некоторые приходят к тому, что начинают кэшировать кэш IDE :)
<Картинка с Ди-Каприо с прищуренным глазом>

4) Логи сборки


Какой CI-сервер вы используете? Предоставляет ли он удобный интерфейс для просмотра и навигации в логах сборки размером в несколько Гигабайт? К сожалению, мой нет :(

5) История коммитов


Любите ли вы смотреть историю коммитов? Я люблю, особенно в инструменте с графическим интерфейсом (я лучше воспринимаю информацию визуально, не ругайте :).
Вот так выглядит история коммитов в моем репозитории
image

Нравится? Удобно? Лично мне нет!

6) Сломанные тесты


Что происходит, если кто-то смог запушить сломанные тесты/некомпилящийся код в мастер? Вы конечно скажете, что ваш CI не позволяет делать такого. А что насчет нестабильных тестов, которые проходят у автора, и ни у кого кроме? А теперь представьте, что этот код растекся на машины 300 разработчиков, и ни один из них не может собрать проект? Что делать в такой ситуации? Ждать, когда автор заметит и исправит? Исправлять за него? Откатывать изменения? Конечно в идеале, стоит коммитить только хороший код, и писать сразу без багов. Тогда такой проблемы возникать не будет.
(для тех, кто в танке и не понял намеков, речь о том, что негативный эффект, если это происходит в репозитории с 10 разработчиками и в репозитории с 300 будет немного разный)

7) Merge bot


Слышали когда-нибудь о такой штуке? Знаете, зачем она нужна? Будете смеяться, но это еще один инструмент, который не должен был бы существовать :) Вот представьте, что время сборки вашего проекта составляет 30 минут. И у вас над проектом работает 100 разработчиков. Предположим, что каждый из них пушит по 1 коммиту в день. Теперь представьте честный CI, который позволяет мерджить изменения в мастер только после того, как они были применены к самому свежему коммиту из мастера (rebase).

Внимание, вопрос: сколько часов должно быть в сутках, чтобы такой честный CI-сервер смог смерджить изменения от всех разработчиков? Правильный ответ, 50. Кто ответил верно, может взять с полки пряник. Ну или представьте, как вы только что отребейзили свой коммит на самый последний коммит в мастер, запустили сборку, а когда она завершилась, мастер уже уехал на 20 коммитов вперед. Все сначала?

Так вот merge bot или merge queue — это такой сервис, который автоматизирует процесс ребейза всех мердж реквестов на свежий мастер, прогон тестов и непосредственно сам мердж, а также может еще и объединять коммиты в батчи и тестировать их вместе. Очень удобная штука. Смотрите mergify.io, k8s test-infra Prow от Google, bors-ng и др. (обещаю написать про это подробнее в будущем)

Теперь к менее техническим проблемам:

8) Использование единого build tool


Честно говоря, для меня до сих пор загадка, зачем собирать весь монорепозиторий с помощью одной общей системы сборки. Почему бы не собирать javascript Yarn'ом, java — gradle'ом, Scala — sbt и т.д.? Если кто-то знает ответ на этот вопрос (не догадывается или предполагает, а именно знает) напишите в комментариях.

Конечно, это кажется очевидным, что использование одной системы сборки лучше, чем нескольких разных. Но все же понимают, что любая универсальная вещь заведомо хуже, чем специализированная, т.к. она скорее всего имеет только подмножество функций всех специализированных. Но что еще хуже, разные языки программирования могут иметь разные парадигмы в плане сборки, управления зависимостями и т.д., которые будет очень трудно завернуть в одну общую обертку. Не хочу вдаваться в детали, приведу один пример про bazel (подробностей ждите в отдельной статье) — мы нашли 5 независимых имплементаций правил сборки javascript для bazel от 5 разных компаний на GitHub, наряду с официальной от Google. Стоит задуматься.

9) Общие подходы


В ответ на оригинальную статью CTO из Chef написал свой ответ Monorepo: please do!. В своем ответе он утверждает, что «главное в монорепо, это то, что он заставляет разговаривать и делает недостатки видимыми». Он имеет в виду, что когда вы захотите изменить свой API, то вы вынуждены будете найти все его использования и обсудить свои изменения с мейнтейнерами этих кусков кода.

Так вот мой опыт ровно противоположный. Понятно, что это очень сильно зависит от инженерной культуры в команде, но я вижу в этом подходе сплошные минусы. Представьте, что у вас используется некий подход, который верой и правдой служил вам на протяжении какого-то времени. И вот вы решили по какой-то причине, решая схожую проблему, использовать немного другой способ, возможно более современный. Какова вероятность того, что добавление нового подхода пройдет ревью?

В своем недавнем прошлом я несколько раз получал комментарии типа «у нас уже есть проверенный путь, используй его» и «если хочешь внедрить новый подход, обнови код во всех 120 местах, где используется старый подход и получи аппрув от всех команд, которые ответственны за эти куски кода». Обычно на этом энтузиазм «инноватора» заканчивается.

А сколько, по-вашему, будет стоить написание нового сервиса на новом языке программирования? В полирепозитории — нисколько. Создаешь новый репозиторий и пишешь, да еще и берешь самую подходящую системы сборки. А теперь то же самое в монорепозитории?

Я прекрасно понимаю, что «стандартизация, переиспользование, совместное владение кодом», но проект должен развиваться. По моему субъективному мнению, монорепозиторий скорее препятствует этому.

10) Open source


Недавно меня спросили: "а есть ли open source инструменты для монорепозиториев?" Я ответил: «Проблема в том, что инструменты для монорепозиториев, как ни странно, разрабатываются внутри самого монорепозитория. Поэтому выложить их в open source оказывается довольно затруднительно!»

Для примера посмотрите на проект на Github с плагином для bazel для Intellij IDEA. Google разрабатывает его в своем внутреннем репозитории, а затем «выплескивает» части от него в Github с потерей истории коммитов, без возможности отправить pull request и так далее. Я не считаю это open source (вот пример моего небольшого PR, который был закрыт, вместо мерджа, а затем изменения появились в следующей версии). Кстати этот факт упомянут в оригинальной статье, что монорепозитории мешают выкладыванию в open-source и созданию коммьюнити вокруг проекта. Думаю, многие не придали особого значения этому аргументу.

Альтернативы


Что ж, если говорить о том, что же делать, чтобы избежать всех этих проблем? Совет ровно один — стремитесь иметь репозиторий как можно меньшего размера.
А при чем же здесь монорепозиторий? А ровно при том, что этот подход лишает вас возможности иметь маленькие, легкие и независимые репозитории.

Какие недостатки есть у подхода полирепозиториев? Я вижу ровно 1: невозможность отслеживать, кто является потребителем твоего API. Особенно это касается подхода в микросервисах «share nothing», при котором код не шарится между микросервисами. (Кстати, как думаете, этот подход кто-нибудь использует в монорепозиториях?) Эту проблему, к сожалению, необходимо решать либо организационными средствами, либо пытаться использовать инструменты для браузинга кода, которые поддерживают независимые репозитории (например, https://sourcegraph.com/).

А что насчет комментариев типа «мы пробовали полирепозитории, но потом нам пришлось постоянно имплементить фичи сразу в нескольких репозиториях, что было утомительно, и мы слили все в один котел»? Ответ на это очень простой: «не надо путать проблемы подхода с неправильной декомпозицией». Никто не утверждает, что в репозитории должен лежать ровно один микросервис и все. В мою бытность использования полирепозиториев мы прекрасно складывали семейство тесно связанных микросервисов в один репозиторий. Тем не менее, с учетом того, что сервисов было более 100, таких репозиториев было больше 20. Самое главное, о чем нужно думать в плане декомпозиции, это то, как эти сервисы будут деплоиться.

А как же аргумент про версии? Ведь монорепозитории позволяют не иметь версий и деплойть все из одного коммита! Во-первых, версионирование — это самая простая из всех озвученных здесь проблем. Даже в такой старой штуке как maven есть maven-version-plugin, который позволяет зарелизить версию всего в один клик. А во-вторых, и в-главных, есть ли у вашей компании мобильные приложения? Если да, то у вас уже есть версии, и вы никуда от этого не денетесь!

Ну есть же еще самый главный аргумент в поддержку монорепозиториев — он позволяет сделать рефакторинг по всей кодовой базе в один коммит! На самом деле, нет. Как было упомянуто в оригинальной статье, из-за ограничений, которые накладывает деплой. Вы должны всегда иметь в виду, что какое-то продолжительное время (продолжительность зависит от того, как у вас выстроен процесс) вы будете иметь 2 версии одного и того же сервиса параллельно. Например, на моем прошлом проекте у нас система находилась в таком состоянии несколько часов при каждом деплое. Это приводит к тому, что нельзя проводить глобальные рефакторинги, затрагивающие интерфейсы взаимодействия, в один коммит даже в монорепозитории.

Вместо заключения:


Итак, тем уважаемым и немногочисленным коллегам, которые работают в Google, Facebook и т.д. и придут сюда защищать свои монорепозитории, хочется сказать: «Не волнуйтесь, вы все делаете правильно, наслаждайтесь своим тулингом, на который было потрачено сотни тысяч или миллионов человекочасов. Они уже потрачены, так что если вы не будете использовать, то и никто не будет».

А всем остальным: «Вы не Google, не используйте монорепозитории!»

П.С. как заметил многоуважаемый Bobuk в подкасте радио-Т при обсуждении оригинальной статьи: «в мире есть ~20 компаний, которые умеют в монорепозиторий. Остальным даже не стоит пытаться».
+45
~10800

комментарии (100)

+2
+3 –1
amarao ,  
Чисто формально, операционные системы и IDE разработчиков тоже должны жить в том же репозитории по этой логике. Включая сам гит. Не?

На самом деле отлично работает модель слоёв. Базовый слой — ОС и стандартные утилиты, поставляемые мейнтейнером дистрибутива или тем, что заменяет дистрибутив у виндузятников. В контексте образов ОС для облаков и т.д. грань становится чуть менее явной (сами свои образа собираем), но вне зависимости от того, «кто», это отлично выделяемый слой.

Следующий слой — кастомные версии нужного нам публичного ПО. Это включает в себя как припиненые версии (потому что в 1.1.3 сломано, и мы сидим на 1.1.1), и версии с собственными патчами.

Следующий слой — публичные зависимости «нашего» софта.

Следующий слой — наши зависимости уровня утилит и полностью автономных сущностей.

Дальше «наши библиотеки» общего пользования.

И уже можно делать монорепозиторий из всего остального.
0
gecube ,  
Так какую структуру репозиториев предлагаете? Как я понял, не единый общий монорепо на все, а коллекцию таких репозиториев среднего размера.
0
amarao ,  
Я ж говорю, слои. Это не не уровне гита даже, потому что нижние слои часто вообще не имеют исходного текста в привычном виде. Это слои инфраструктуры. В целом, это гигантский топик, базовые уровни я описал сверху.

Где-то тут ещё системы управления конфигурациями (а у них там своя система с переиспользованием кода — роли/cookbook'и), и вся инфраструктура CI/CD (сервер, на котором лежит монорепа, управляется системой управления конфигураций, которая лежит где? А код для этого сервера, условный гитлаб, откуда ставится?).
0
HSerg ,  
Ну есть же еще самый главный аргумент в поддержку монорепозиториев — он позволяет сделать рефакторинг по всей кодовой базе в один коммит! На самом деле, нет. Как было упомянуто в оригинальной статье, из-за ограничений, которые накладывает деплой.
Часто деплой не накладывает ограничений (это, например, характерно для заказной разработки), так что легко просматриваемый reviewer и собираемый build-сервером единственный атомарный PR — действительно существенный плюс.

P.S. В названии статьи и тексте потерялось «в git».
0
kanu ,  
Ну есть ещё софт, который работает 5*8 и обновляется по выходным с даунтаймом.
Это не отменяет того, что я написал, что специфика вашего деплоя такова, что не накладывает на это ограничений. Что же, вам повезло, для вас этот недостаток неактуален.
0
anton0xf ,  

Т.е. вы разрабатываете проекты на заказ в общем монорепозитории вашей компании, где хранятся и все разрабатываемые сейчас, и уже готовые заказы? А исходники этих проектов вы заказчикам отдаёте? Как?

+2
kanu ,  
Ну как, копируют в папочку и нарезают на диск :)
+1
gecube ,  
Между прочим, папочка и на диск (или usb flash drive) — это единственный верный с точки зрения гос. органов способ передачи интеллектуальной собственности. Ну, естественно, еще акты, закрывашки и прочее… Это же Россия!
0
kanu ,  
В мое время распечатывали исходники в 4х экземплярах и сшивали :)
–3
tgz ,  
Что бы жить без моонрепы нужны интсрументы, а их или нет, или всем просто лень. И так сойдет. А потом уже поздно что-то менять.
+5
+6 –1
SirEdvin ,  
Мне казалось посыл статьи как раз в том, что чтобы жить в монорепе, нужны инструменты.

С полирепой отлично живется, вроде как, инструментов море.
+8
+9 –1
ToSHiC ,  
Фуры не нужны, ведь всё можно перевезти в багажнике легковушки, просто их понадобится много.

А по делу — основным минусом полирепозиториев является невозможность быстро обновиться. В худшем же случае в какой-то момент невозможно использовать одновременно библиотеки A и B, потому что они обе зависят от библиотеки C, только разных версий, и конечно же в итоговой программе такой зоопарк не соберётся.

Я сам вообще не далеко не фанат монореп, но говорить о том, что набор независимых репозиториев существенно лучше — это самообман. И чем больше команд, тем больнее кушать этот кактус.
0
snizovtsev ,  

Видел интересный (и правильный) подход к решению проблемы — https://github.com/google/cargo-raze. Оно по constraints всего дерева зависимостей Cargo.toml старается сгенерировать общий Cargo.lock (список версий библиотек) такой, чтобы удовлетворить всех.

+2
kanu ,  
Ну так maven делает такой резолв версий зависимостей уже примерно лет 100. Причем политику можно задать, или для конкретной библиотеки разрулить руками и зафиксировать версию.
0
ToSHiC ,  
Но в той ситуации, что я описал, оно просто скажет «такое невозможно собрать», счастья вам от этого не прибудет.
+1
kanu ,   * (был изменён)
А как вы в монорепе сделаете, чтобы А и Б зависели от разных версий Ц? Точнее, вы сделаете, только непонятно, чем тут монорепозиторий помогает? Будет ровно такой же конфликт транзитивных зависимостей, который нужно решать.
Тем, что он вам не позволит в библиотеках А и Б завязаться на разные версии Ц? Да позволит, куда денется. И точно также вы узнаете об этом в самый последний момент.
+2
ToSHiC ,  
Очевидно, A и B в этом случае просто физически не могут зависеть от разных версий C, ведь C может существовать в репозитории только в одной версии в каждый момент времени, и такой проблемы не существует.
0
+1 –1
vintage ,  
Решается элементарно копипастой.
0
+1 –1
ToSHiC ,  
За это надо по рукам бить, сильно.
+2
balexa ,  
Это вы рассказываете про страну эльфов какую-то? В реальном мире все немножко не так. Если от С зависят проекты A, B, ...Z, то у разработчика проекта А, если ему надо внести изменения в С есть несколько вариантов.
1. Внести изменения в С и поправить все остальные проекты, убедить их проревьюить измнения, протестить и т.д. Это в случае популярности С он будет делать примерно вечность. Не говоря уже про то, что он должен знать, кто зависит от проекта С, в т.ч. и транзитивно.
2. Внести обратно-совместимые изменения в С. Чтобы все могли пользоваться и старой версией и новой. Ничем не отличается от полирепы.
3. Скопипастить себе кусок кода. Теперь у нас есть проект С(А) которым пользуется А и есть проект С которым пользуются все остальные. А на самом деле есть С(B) и так далее. И это к сожалению факт.
Тут недавно яндекс рассказывал что у него десяток проектов на каждого разработчика приходится. Думаете там копипасты нет?
0
anjensan ,  
2. Внести обратно-совместимые изменения в С. Чтобы все могли пользоваться и старой версией и новой. Ничем не отличается от полирепы.
В полирепе можно, если очень надо, внести обратно-несовместимые изменения, бампнув мажорную версию. А клиенты A, B, ...Z будут переходить уже по мере надобности и сил. А вот в монорепе да, копипаста… Ну или забить, и *не* вносить изменения (или делать это годами)…
+1
ToSHiC ,  
А клиенты A, B, ...Z будут переходить уже по мере надобности и сил.

К сожалению, это означает «никогда», и срочное обновление из-за какого нибудь бага будет ооооочень болезненным. Да ещё и поддерживать старые мажорные версии придётся годами, потому что у всех планы, продакшен сломается и т.д. Это из собственного опыта, если что.
0
ToSHiC ,  
Разработчику А ничего не надо, С вообще развивается другими людьми. И вот это проблема: они то библиотеку развивают, но ни разработчики А, ни разработчики B обычно такие изменения не сильно прям хотят, им базовых фичей хватает с головой. И они ни в варианте с монорепой, ни в варианте с полирепами ничего обновлять не хотят и, следовательно, не обновляют. В варианте с монорепой в итоге за совместимостью и обновлениями голова болит у разработчиков C, а вот при полирепах только административными мерами.

Внезапно, про боль и проблемы полиреп и монореп я знаю не понаслышке как раз по опыту работы в Яндексе :) Так что я знаю, что тут происходит, и какие проблемы есть у действительно больших проектов, а не в репах на пару десятков человек.
+1
anjensan ,   * (был изменён)
Ага, главное чтобы у разработчика C голова от боли в конце-концов не лопнула.
И чтобы новый разработчик C не застрелился, разгребая тонны костылей «обратной совместимости» чтобы не дай бог ченить не сломать. И чтобы этот разработчик не «понаписывал» в исходниках A..Z, ведь контекста он не знает…
Тоже не идеал на самом деле.

Внезапно, про боль и проблемы полиреп и монореп я знаю не понаслышке как раз по опыту работы в Яндексе
А я знаю по опыту работы в гугле, и?
0
gecube ,  
Ну, давайте про боли монореп. Больше кейсов, больше интересных решений, больше велосипедов. Расскажите, пожалуйста, если это, конечно, не нарушает NDA. Хотя можно писать и в общем — за это точно никого не побьют, а только скажут спасибо.
+1
ToSHiC ,  
Да всё по классике: свой тулинг, тяжело с контрибами жить, статическая линковка, не гит (хотя это решаемый вопрос, в MS вот зафиксили же).
Плюсы: статическая линковка, воспроизводимость сборок (вот это очень хорошее свойство), нормальный поиск и возможность глобального рефакторинга, отсутствие ада зависимостей от минорных версий. Пожалуй, сюда же можно написать и тулинг: CI/CD получаешь бесплатно.

В общем, для плюсов/го/раста/etc работает относительно неплохо, для питона так себе, для ноды вообще всё сложно. Базел не пробовал, так что про него особо ничего сказать не могу. В гугле/фб не работал, а на предыдущем месте монорепа была для одного большого монопроекта, там вариантов не было особо.
0
kanu ,  
Ну а если Ц — это сторонняя библиотека?
+1
balexa ,   * (был изменён)
невозможность быстро обновиться.

Я не очень понял, почему именно в монорепе возможно. Почему обновить два проекта А и B будет медленнее, чем обновить всю монорепу в стопицот проектов.

конечно же в итоговой программе такой зоопарк не соберётся.

И как монорепа решает такую проблему? Просто интересно, как относится резолв зависимостей и прочие депенденси хеллы к системе контроля версий.
0
gecube ,  
И как монорепа решает такую проблему? Просто интересно, как относится резолв зависимостей и прочие депенденси хеллы к системе контроля версий.

Я предполагаю, что при работе в монорепе органически появляется требование, что нужно использовать именно те версии библиотек, которые в ней есть. Это же и косвенная причина, почему все зависимости инжектируются в это монорепо (т.е. все 3rd party библиотеки туда втягиваются и фиксируются). Т.е. условно сделали сервисы А и Б. Они оба зависят от В. Переписали А, оно потянуло новую версию В. Сборка и тесты Б сломались. Пришлось переписывать Б на новую версию В. И так далее.

Казалось бы — мы пытаемся сделать проще и дешевле разработку, а получается ровно наоборот.
0
balexa ,  
Да это все понятно. Непонятно чем это отличается от полирепы. Ну, кроме того, что третьесторонние библиотеки лежат не в общей пахнущей куче, а там где им положено
0
gecube ,  
Ну, может тем, что всегда есть только последняя, крайняя версия репозитория (ну, и набор версионированных артефактов где-то сбоку)? И не нужно думать о матрице совместимости (я про нее тут упомянул).
+2
balexa ,   * (был изменён)
Да, я читал тот комментарий. Не знаю, я за 10+ лет работы в самых разных организациях такого не видел. Ну нет никакой матрицы, нет ни у кого требования развертывать разные версии разных микросервисов. Все сидят на последних версиях, у всех есть фичи, багофиксы и так далее. Смысла в матрице я слабо представляю, ну разве что это какой-то коробочный продукт, но и тогда — все это обычно поставляется скопом.

И как и было замечено, что в мультирепе, что в моно — разными проектами занимаются разные люди, и если ваш сервис используется другими командами, нереально заменить везде АПИ, да еще и зарелизить это везде одновременно. Никто так никогда делать не будет. Поэтому что в монорепе, что в мульти — вы делаете новую версию АПИ, рассылаете всем причастным уведомления, потом отслеживаете кто еще использует старую версию и только потом, когда она никому не нужна ее убирают. То что выделено курсивом может занимать не один год и даже не два.
–1
ToSHiC ,  
Альтернатива — в полирепах в принципе нету возможности ограничить использование старых версий. Я видел как варианты с использованием собранных артефактов (deb-пакеты, так уж сложилось, что я в основном касался мира c++ разработки под linux), так и сложные конструкции c git submodules. Во всех этих случаях всё заканчивалось тем, что все в итоге забивают на обновление какой либо библиотеки, количество изменений постепенно растёт, и потом обновление, связанное с каким нибудь security фиксом становится невероятной болью.

И нет, невозможно все эти библиотеки превратить в микросервисы, т.к. это банально медленно. Локальный вызов стоит сотни микросекунд, сетевой — единицы миллисекунд, как минимум, а 99 процентиль — десятки и сотни миллисекунд, + он всегда может не уложиться в таймаут для конкретного запроса.
0
balexa ,   * (был изменён)
У плюсов вообще своя атмосфера, связанная с отсутствием вменямого пакетного менеджера, поэтому плюсовики вынуждены держать все зависимости в системе контроля версий и пересобирать их.

Но опять таки, что в полирепах, что в монорепах — обновление третьесторонней библиотеки это ручная работа. Если вы забьете на обновление либы, то она и в монорепе сама не обновится. Я вообще этого аргумента не понимаю.

И да, вы выдвинули тезисы — я спросил почему так. Вы резко тезисы сменили. Я повторю еще раз вопрос — 1. почему два проекта A и B будут обновляться дольше, чем стопицот проектов из полирепы. 2. Как относится резолв зависимостей и прочие депенденси хеллы к системе контроля версий.

Фактически вы сейчас рассказываете, что использование всегда LATEST версии принудительно — это универсальное решение всех проблем. Нет, это не так.
0
ToSHiC ,   * (был изменён)
Я повторю еще раз вопрос — 1. почему два проекта A и B будут обновляться дольше, чем стопицот проектов из полирепы.

Потому что в монорепе обновление — это вопрос технический, надо взять и поменять в 100500 местах код, а в полирепах — административный, надо заменеджить каждую команду обновить свой код на новую версию, и пока они не обновятся — поддерживать 2, 3 мажорных версии и чинить в них баги параллельно. Вы же не можете самовольно решить, что не будете чинить баги в библиотеке, из-за которой вот сейчас лежит прод, правда?
2. Как относится резолв зависимостей и прочие депенденси хеллы к системе контроля версий.

В случае монорепы всё это не нужно, т.к. именно сборка делается из транка. Я подразумеваю, что монорепа == trunk based development.

Безусловно, это не решение всех проблем, но тут уже вторую статью все в комментариях говорят, что монорепа — это адище, а от большого количества реп волосы становятся мягкими и шелковистыми, при этом с проблемами полиреп в проектах с большим количеством команд не сталкивались. Вот всё далеко не так просто, и гугл/фб/яндекс/мс не от хорошей жизни на монорепах сидят.
+1
balexa ,   * (был изменён)
монорепе обновление — это вопрос технический, надо взять и поменять в 100500 местах код

Признаюсь я думал вы про git pull говорите. Теперь понял что вы про обновление зависимости.

Но если просто поменять код — то и в полирепе сделайте то же самое. Выкачайте 100500 репозиториев и поменяйте все места. Затем запушьте. В чем проблема?

Вы владеете кодом всех проектов в кашей компании? Тестировать, ревьюить, выкатывать, иметь ролбек план, делать все эти ваши сини-зеленые развертывания не надо? Странно слышать от руководителя яндекса что обновление — это «поменять код». Поменять код это дай бог треть работы всей. Код еще надо проревьюить, оттестировать, выкатить, мигрировать данные и т.п. Не говоря уже про то, что у вас не будет владения кодом для всех 100500 проектов. А значит — «надо заменеджить каждую команду обновить свой код на новую версию». Только одновременно.

Вы же не можете самовольно решить, что не будете чинить баги в библиотеке, из-за которой вот сейчас лежит прод, правда?

А зачем? Это делается откатом нововыкаченного сервиса. Одного, а не 100500 который вы обновили. А если вы чините багу в библиотеке в то время как лежит ваш сервис на проде, то вы либо ждете пока ваш хотфикс затестят, либо имеете нехилый шанс положить остальные 100499 сервисов.
И да, в рассматриваемом примере как раз таки монорепа мешает.

при этом с проблемами полиреп в проектах с большим количеством команд не сталкивались

Я сталкивался. И когда в гугловом подразделении работал, и на прошлом месте работы в дойче банке (это если что, к вашему замечанию, что дескать в яндексе действительно большие проекты, а у остальных по 20 человек).
Но для полиреп эти все проблемы хорошо известны, решаемы, есть куча готовых хорошо оттестированных инструментов.
Полирепа хорошо разграничивает разные зоны ответственности, поскольку все равно разработчик не может знать и владеть кодом из стопицот проектов.
Проблемы с зависимостями библиотек и тем что всем лень обновлять версию либы монорепа не решает. А проблем из-за нее — куча. И собственно монорепы используют в основном компании, которые пишут свои велосипеды для всего, включая большую часть инструментов разработки.
+1
gecube ,   * (был изменён)
И собственно монорепы используют в основном компании, которые пишут свои велосипеды для всего, включая большую часть инструментов разработки.

Это прям отличное описание политики Яндекса и Гугла. Мелкие компании (=стартапы) возможности строить свои велосипеды на каждый чих не имеют. И им приходится пользоваться сторонними продуктами (т.е. встает задача фиксации версий этих самых сторонних продуктов и далее поддержания их в актуальном состоянии)
0
ToSHiC ,  
Но если просто поменять код — то и в полирепе сделайте то же самое. Выкачайте 100500 репозиториев и поменяйте все места. Затем запушьте. В чем проблема?

А как вы их найдёте то? Сможете найти на гитхабе, например, всех пользователей folly?
Вы владеете кодом всех проектов в кашей компании? Тестировать, ревьюить, выкатывать, иметь ролбек план, делать все эти ваши сини-зеленые развертывания не надо? Странно слышать от руководителя яндекса что обновление — это «поменять код». Поменять код это дай бог треть работы всей. Код еще надо проревьюить, оттестировать, выкатить, мигрировать данные и т.п. Не говоря уже про то, что у вас не будет владения кодом для всех 100500 проектов. А значит — «надо заменеджить каждую команду обновить свой код на новую версию». Только одновременно.

Представьте себе, что это минорное изменение, которое не требует изменения кода. Тестирование и деплой в любом случае выполняются в соответствии с релизным циклом каждого компонента. Зато вы хотя бы получите автоматический запуск тестов для всех зависимых проектов и увидите, что своим изменением вы ничего не сломали.
А зачем? Это делается откатом нововыкаченного сервиса. Одного, а не 100500 который вы обновили. А если вы чините багу в библиотеке в то время как лежит ваш сервис на проде, то вы либо ждете пока ваш хотфикс затестят, либо имеете нехилый шанс положить остальные 100499 сервисов.
И да, в рассматриваемом примере как раз таки монорепа мешает.

Это если баг свежий, если он там 5 лет живёт и начал триггериться только сейчас, как это было с високосной секундой в ядре linux, например — то откатываться некуда.
Я сталкивался. И когда в гугловом подразделении работал, и на прошлом месте работы в дойче банке (это если что, к вашему замечанию, что дескать в яндексе действительно большие проекты, а у остальных по 20 человек).

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

Если бы для полиреп это были решенные проблемы — то dependency hell бы не существовало.
И собственно монорепы используют в основном компании, которые пишут свои велосипеды для всего, включая большую часть инструментов разработки.

Факт. Но он не подтверждает утверждение, что не надо использовать монорепы.
0
balexa ,   * (был изменён)
А как вы их найдёте то? Сможете найти на гитхабе, например, всех пользователей folly?

Наверное нет. Однако обратите внимание, что фейсбук выкладывает свою библиотеку и ей пользуются. Я не очень понимаю, к чему этот вопрос. К тому что по вашему, весь код всех этих пользователей должен лежать в одной репе, куда будет комитить весь гитхаб? Или что?
Расскажите, как бы это работало в монорепе. Мне правда интересно.

Зато вы хотя бы получите автоматический запуск тестов для всех зависимых проектов и увидите, что своим изменением вы ничего не сломали.

Т.е. всех проектов использующих библиотеку фейсбука, я верно понимаю?

Это если баг свежий, если он там 5 лет живёт и начал триггериться только сейчас, как это было с високосной секундой в ядре linux, например — то откатываться некуда.

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

Если бы для полиреп это были решенные проблемы — то dependency hell бы не существовало.

Да что вы заладили со своим хеллом, это не самое частое явление. Вот я беру ваш же пример — есть линукс, есть folly, есть gcc как инструмнт сборки, есть буст, есть миллиард приложений написаных с их использованием. И все как-то живут в своих репозитариях. Я не очень понимаю, к чему тут вообще линукс и фейсбук и как это относится к монорепе. Скорее ваш пример показывает что мультирепа — удобнее.

Факт. Но он не подтверждает утверждение, что не надо использовать монорепы.

Да вполне — если ваша контора не готова выделить отдельную команду чтобы писать для себя системы сборки, версионирования, индексации и прочий тулинг — то монорепа не нужна.
0
ToSHiC ,  
Пример с фолли был гиперболой для рабочей ситуации какой-то компании, код которой хранится в наборе гит реп в модном корпоративном гитхабе, битбакете или ещё как либо, сама фолли же — та самая библиотека С, которую вы меинтейните, внесли туда свои изменения и хотите, чтобы они до всех доехали. Для этого можно
  • не делать ничего, через какое-то время это приведёт к тому, что попросят сделать хотфикс, причём в старой версии — потому что текущая слишком далеко убежала вперёд, а баг вот сейчас и откат на предыдущую версию не поможет
  • найти всех пользователей и сделать PR в их код/сборочные зависимости, чтобы они перешли на новую версию, а для этого надо найти всех, кто это библиотеку использует

Монорепа очевидно не позволяет выбрать первый вариант, и существенно облегчает второй. Надеюсь, теперь пример стал понятен?

Т.е. всех проектов использующих библиотеку фейсбука, я верно понимаю?

Конечно. Всех, что разрабатываются в вашей компании.

Да что вы заладили со своим хеллом, это не самое частое явление. Вот я беру ваш же пример — есть линукс, есть folly, есть gcc как инструмнт сборки, есть буст, есть миллиард приложений написаных с их использованием.

Ага, и ещё замечательная пара пакетов libcurl4-gnutls-dev и libcurl4-openssl-dev, которые «инфицируют» дерево зависимостей — если хотя бы в одном месте слинковались с libcurl4-openssl-dev, то все-все-все остальные библиотеки в рамках этого бинарника ни в коем случае не должны быть слинкованы с libcurl4-gnutls-dev. Это то, что сходу в голову пришло. Для обновления gcc надо пересобрать ВСЁ, т.к. библиотеки становятся бинарно несовместимыми. Все живут конечно, пока маленькие, как только появляется несколько десятков библиотек с активной разработкой, так появляются проблемы с взаимной совместимостью, завязками на минорные версии и т.д.

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

Но не обязательно писать свой — можно взять Bazel, как это сделали Dropbox, Uber и SpaceX.
0
GrigoryPerepechko ,  
>> Лично у меня часто бывают ситуации, когда хочется склонировать проект в соседнюю папку, поковыряться в нем, а затем удалить
git worktree
0
petuhov_k ,  
hg share
+1
gecube ,   * (был изменён)
Монорепозиторий на всю организацию — зло
Репозитории на каждый отдельный маленький компонент (вроде результатом сборки каждого репо должен быть только один артефакт) — зло, правда, меньшее.
Истина где-то посередине. Видимо, оптимально, когда есть набор проектов, которые существуют в организации. И для каждого проекта выделяется отдельный монорепозиторий, из которого он и собирается. Всякий внешний стафф (тулинги, служебные образа) — можно загонять или в отдельные репозитории, или в отдельный монорепозиторий.
Вот тогда и будет счастье.
В случае же кучи микрорепозиториев вы обрекаете себе на ад микроменеджмента зависимостей между ними.

p.s. самая боль с монорепо — это если есть внешние подрядчики (делают какие-то микросервисы) или внешние потребители кодовой базы (но им не нужно «светить» все содержимое репы) и нужно как-то синхронизировать работу с ними.
+1
kanu ,  
Никто не утверждает, что в репозитории должен лежать ровно один микросервис и все. В мою бытность использования полирепозиториев мы прекрасно складывали семейство тесно связанных микросервисов в один репозиторий.
0
gecube ,  
Я верю, вот и пытаюсь сматчить свой опыт и свои соображения.

Касательно монорепо еще момент. Мне кажется, что инструмент git и все надстройки над ним (github/gitlab) вообще не про монорепо. От слова совсем. git прагматично решал одну конкретную задачу — задачу г-на Торвальдса по разработке ядра. Но так уж получилось, что все остальные системы управления версиями оказались не очень пригодными к промышленной эксплуатации (ну, может кроме hg, который все еще популярен в определенных кругах). Или мучения Microsoft, которым пришлось прикручивать отдельный слой файловой системы, что git нормально работал на их объемах кода — GFVS. Почитать, можно тут:
www.nixp.ru/news/14046.html
en.wikipedia.org/wiki/Git_Virtual_File_System
github.com/Microsoft/VFSForGit
+1
kanu ,  
Это правда, в этом и проблема, что такие инструменты как GitHub предназначены прежде всего для маленьких команд, коих сейчас огромное число. И так почти со всеми инструментами. И это неспроста — это диктует рынок.
+4
ApeCoder ,  
Совет ровно один — стремитесь иметь репозиторий как можно меньшего размера.

Один файл — один репозиторий!

+1
MikailBag ,   * (был изменён)

Один байт — один репозиторий.
Кстати, так можно радикалько снизить их количество благодаря переиспользованию.
А вообще, так выглядит 90% JS-библиотек

+1
kanu ,  
если есть внешние подрядчики

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

А в любой и не надо делать доступ.


оттуда делают патчи.
Вариант. Но тогда Вам нужно два тулинга:
  • один для синхронизации из Вашего внутреннего репо в тот, в котором работают подрядчики
  • и наоборот — для синхронизации из репы подрядчиков в Ваш.

Сами патчи — можно накладывать git'ом, но их нужно заранее готовить.


К тому же, в рамках парадигмы github & gitlab выгоднее это все производить через fork основного репозитория и разработчики шлют merge request. Понятно, что это тоже толкает не на укрупнение репозиториев, а на умельчение (чтобы не показывать лишнего).

+1
kanu ,  
В случае же кучи микрорепозиториев вы обрекаете себе на ад микроменеджмента зависимостей между ними.

Я работал в парадигме share-nothing, там такой проблемы нет совсем. Т.к. зависимостей между микросервисами нет. А если сервисы тесно связаны, их нужно хранить вместе.
0
gecube ,  
Я работал в парадигме share-nothing, там такой проблемы нет совсем.

Смотрите. У Вас есть продукт. Он состоит из микросервисов. Очевидно, что микросервисы взаимодействуют друг с другом по публичному API (HTTP, REST, protobuf etc.). И не все комбинации версий микросервисов жизненноспособны. Поэтому важно, чтобы продукт был консистентным — держать эту матрицу совместимости где-либо. В случае кучи микрорепозиториев приходится эту интеграционную информацию выносить в отдельный репозиторий для интеграции всего. А тогда, получается, можно было сразу все пихать в монорепу.
А если сервисы тесно связаны, их нужно хранить вместе.

К вопросу связанности. Можно решить и не через монорепу, а через механизмы git по включению кода из разных репозиториев друг в друга. Те же submodules. Они не идеальны, но отчасти решают задачу.
+1
kanu ,  
В целом вы правы, но при подходе share nithing можно вообще ничего не хранить — каждый сервис содержит свою актуальную swagger-спецификацию, которую клиенты используют и обновляют.
Я хочу отметить, что если разговор о больших компаниях, то чаще всего отдельные сервисы разрабатываются отдельными командами. Поэтому все равно, если вы решите изменить API своего сервиса, вы не сможете переписать код всех клиентов, просто потому, что вы его не знаете и не владеете им. Поэтому, вы просто сообщаете другим командам, что у вас появились новые методы в API, но оставляете старые как deprecated.
А вообще ещё лучше делать все изменения обратно совместимыми. Если у вас API публичный, вы не владеете кодом клиентов и не можете заставить их его обновить, у вас собственно и нет других вариантов.
0
snizovtsev ,  

Не так важно как разбит код, но вот моносборка для C++, Go, Rust, Haskell — это must have, без неё очень больно жить. Отладочные символы, кросскомпиляция, профилирование, инструментирование, LTO, compile_commands.json, да и просто корректная инкрементальная сборка — всё это нормально работает только тогда, когда все зависимости бинарника собирает одна тулза. Вроде как Bazel так умеет — несколько репозиториев, но сборка центральная.

0
TheKnight ,  
Достаточно воспользоваться source-based менеджером зависимостей.
+1
gecube ,  
С++ это вообще отдельная боль.
Остальные попроще, т.к. появились попозже и, соответственно, уже имеют разные механизмы сборок и разные механизмы управления зависимостями (на уровне экосистемы языка и самого языка).
+8
vintage ,   * (был изменён)
CTO из Chef написал свой ответ Monorepo: please do!.. В своем ответе он утверждает, что «главное в монорепо, это то, что он заставляет разговаривать и делает недостатки видимыми».

Интересно, только у меня сложилось впечатление, что большинство CTO попросту профнепригодны? Других способов заставить людей общаться, конечно же, нет, кроме как создать всем общий геморрой.

+1
NeoPhix ,  
Я правильно думаю, что большая часть проблем (будь то моно- или поли-) репозиторий возникает из-за следующих факторов:
1. Отсутствие нормальной декомпозиции кода (читай, стремная архитектура с высокой запутанностью между проектами без четких границ этих самых проектов)
2. Отсутствие людей, которые хотят/могут заниматься разделением и рефакторингом взаимодействия проектов внутри компании?
+2
kanu ,  
Думаю, что это может быть связано, но далеко не всегда. Но в оригинальной статье автор говорит о том, что монорепозиторий провоцирует плохую архитектуру и отсутствие декомпозиции.
+1
impwx ,  
Основная причина, по которой я предпочитаю монорепозитории — атомарные коммиты. У нас часто бывает так, что фича требует изменений в нескольких компонентах (скрипт миграции БД, пара правок на бэкенде, еще пара на фронте, документация и т.д.) — с другими подходами типа git submodules или подгрузкой зависимостей из пакетов синхронизация и ревью таких изменений превращаются в адище.
+1
vintage ,  
Что у вас происходит, когда вы «атомарно» выкатываете новое апи, а пользователь вот прямо в данный момент заполняет огромную форму в старом клиенте?
+1
impwx ,  
Предметная область позволяет на определенное время запретить новые сессии, дождаться завершения всех текущих (они ограничены по времени) и накатить миграцию.
+1
anjensan ,  
Основная причина, по которой я предпочитаю монорепозитории — атомарные коммиты.
Атомарные коммиты — миф. Нет, ну конечно, если у вас «огромаднейший» монорепо, в котором целый 1 бекенд, целый 1 фронтенд и да еще доки с миграциями в придачу — тогда все работает норм…

Я вот лично встречал, например, специальный пресабмит-чек в одном проекте, не позволяющий зафиксировать изменение, если в нем правятся одновременно файлы из фронтенда и бекенда. И это в монорепозитории, большом таком :)

Причем этот чек еще доходчиво пояснял в сообщении об ошибке, мол править одновременно файлы разных проектов весьма себе плохая идея, ибо деплой циклы не сопадают (да и не могут чисто технически совпадать в общем случае).
0
impwx ,  
Термин «монорепозиторий» применим только к «огромаднейшим» проектам?
0
anjensan ,   * (был изменён)
Ну если у вас по сути один проект, состоящий из нескольких частей, которые лежат в одном репо — нет, это не монорепо. По крайней мере не тот, про который эта статья.

И я не говорил про огромаднейшие проекты.
Проекты разные могут быть. Просто их в монорепе много.
0
locutus ,  

А чем полирепозиторий отличается от различных Depot в монорепозитории Perforce? Для svn есть sparse checkout, очень полезна штука.


А как же выкладывание в open source? Легко: p4-git; git format-patch.

0
gecube ,  
Расскажите про Perforce побольше, пожалуйста. Дело в том, что когда-то давно альтернатив SVN, Rational ClearCase и MS SourceSafe ничего не было. И жизнь была болью. А теперь, когда есть phabricator, git (+github, gitlab), mercurial & co — вроде жизнь бьет ключом, но и необходимость этих энтерпрайз продуктов вроде бы и исчезла.
0
locutus ,  

Ну, как, я пользователь p4, не администратор. Наверное, стоит для моей компании дорого, но при этом с техподдержкой и другими платными плюшками.


Выглядит как набор утилит, собственно сервер, различные клиенты, сервер для code review и много чего ещё, что наверное кто-то использует. Какие плюсы?


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

0
gecube ,  
Знаете, я пока профита относительно gitlab не вижу. Gitlab же можно и бесплатно использовать. И самое главное — в нем можно строить пайплайны для сборки и развертки приложений… Т.е. по факту инвестируешь только время сотрудника (копейки) и вычислительные ресурсы (тоже при грамотном подходе копейки).
А за коробку вроде той, что пользуетесь Вы — нужно отваливать денег несколько раз.
0
locutus ,   * (был изменён)
Для организации размером «100+» нет уже ничего бесплатного. У вас уже точно будут несколько сотрудников, занимающихся gitlab, CI и прочими вещами. Вполне может быть, что начиная с некоторого уровня затрат, становится дешевле покупать готовое решение. А начиная с ещё более высокого уровня — писать собственное.

Free software — там «free as in freedom». Бесплатности Столлман не обещал.

Да, насчёт бесплатности — ценник на gitlab все же конский
0
gecube ,  

Я про это и пишу, если внимательно посмотрите.
А энтерпрайз подписка на гитлаб — ну, да, стоит денег. Но это подписка, с разными уровнями стоимости. Т.е. бизнес может решить, что его удовлетворяет больше в текущий момент времени. А коробка — они и в Африке коробка. Инвестируете единовременно, а потом если не продлите, то можете лишиться обновлений. Или вообще функционала

0
locutus ,  

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

0
anjensan ,  
Вот так выглядит история коммитов в моем репозитории
Так это же легко исправляется! Вот вы сами привели ссылку на сайт «trunkbaseddevelopment»…
Trunk… Based…
Так что просто не нужно делать веток! И история будет красивой и ровной :)
0
kanu ,  
Ха, а мы делаем squash&merge, все ветки на картинке — это временные фича-бранчи :)
Мастер-то, ясно дело, линейный (почти:)
+1
Semenych ,  
Спасибо, интересная статья и отдельное спасибо за конкретные цифры.
0
aspcartman ,  
А все же, почему количество воспринимается как что-то, зависящее от количества разработчиков и что-то, несущее накладные расходы в принципе?

Доведем идею до абсудра: вот у вас в репозитории есть код приложения. И, например, в коде есть множество не связанных классов\пакетов\не важно. Свой домашний класс для работы с UUID, собственная имплементация json-сериализатора, коими нынче принято бороться со скукой в определенных кругах. И таких вот пакетов, скажем, 20.

А потом возьмем и разобьем все это дело на 21 репозиторий. В первом — основной код, и вот таких вот 20 либ. Чтобы ими пользоваться используется просто местный менеджер зависимостей для вашего ЯП — go mod, cocoapods, npm, cargo, вот эти ребята.

Где конкретно здесь появляются неудобства и дискомфорт? И как они изменяются при изменении количества реп с 1 до 100?
0
vintage ,  
А зависит от Б, который зависит от Ц, который зависит от Д. Надо проверить как поведёт себя А с новой Д. И понеслось: собери Д, опубликуй под новой уникальной версией, обнови его версию в Ц, закоммить, повтори всю цепочку ещё 2 раза.
0
aspcartman ,  
Не могу плюсовать, карма зло.

Да, хорошо, т.е неудобства появляются, когда древо зависимостей имеет глубину больше двух. Принято. Это основное неудобство в приведенной ситуации?
0
gecube ,  
Да вообще неудобно ходить по 20+ репозиториев. Гипотетически можно сделать интеграционную репу, которая умеет все выкачивать (submodules, subtree), но тогда возникает вопрос изменения версий каждого компонента.
0
kanu ,  
Да не нужно вам ходить по репам, в больших компаниях все равно у каждой команды свой сервис. В лучшем случае вам понадобится ваш репозиторий и, возможно, парочка соседних для интеграционного тестирования.
0
gecube ,  
А я чем Вам противоречу? Выше же предлагают декомпозировать до состояния «одна репо -один артефакт (один микросервис)».
Я уж не говорю, что предположим, что Вы представляете группу билд или релиз инженеров, которые натягивают шаблоны сборки на все проекты — тогда нужен доступ ко всему.
+1
KShkodkin ,  
Нельзя просто так взять и сказать, что монорепа — фуфло, а полирепа — кул. Для каждой и задачи и проекта и архитектуры и ситуации свои подходы. Сваливать весь код, конфиги и т.п. компании в одну репу — абсурд, но и дробить на сотни мелких репозиториев — тоже. Истина где-то по середине, с зависимостью от внешних факторов. Монорепа удобна для одного или нескольких проектов с десятком сервисов, которые тесно взаимосвязаны между собой, но должны быть отдельными сервисами. Нет смысла в репозиторий, в котором лежит, например, код фронт-энд отрисовки какой-нибудь карты на канвасе, вливать код бэк-энд межсервисного общения. Они никогда не будут взаимодействовать. Универсального подхода нет, всё нужно делать с умом.
0
kanu ,  
Про ум все верно сказано! Это в любом деле так
–1
SirEdvin ,   * (был изменён)
Нет смысла в репозиторий, в котором лежит, например, код фронт-энд отрисовки какой-нибудь карты на канвасе, вливать код бэк-энд межсервисного общения.

Это вы только что сказали, что монорепа — фуфло.


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

0
KShkodkin ,  

А подскажите пожалуйста, как называется тип репозитория, в котором лежит несколько "проектов", но не все проекты компании?


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

0
SirEdvin ,  
А подскажите пожалуйста, как называется тип репозитория, в котором лежит несколько "проектов", но не все проекты компании?

Это вроде все еще полирепы. В самой статье и комментах писали, что вам ничего в полирепе не мешает держать несколько проектов. Скажем, в одной пять, во второй три и в еще двух по одному.


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

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

0
kanu ,  
Ну могу немного не согласиться.
Слышали про twitter.com/monorepi?lang=en — это от Твиттера, у них было 2 монорепозитория :)
Для справки www.gigamonkeys.com/flowers
–2
SirEdvin ,  
Ну так у них же как раз два полирепозитория разделенные признаками языка? Или я не прав?
0
kanu ,  

Название аккаунта как бы намекает — monorepi — это латинское словообразование множественного числа. Т.е. это шуточный аккаунт их 2х монорепозиторий.
Ну и прочитайте статью, там первая половина как раз посвящена истории того, как так вышло

0
intermed ,  
На мой взгляд эти ребята все показали предельно просто.
12factor.net/ru/codebase
Ну и 300 человек на репозиторий конечно перебор по крайней мере для комерческой разработки. Опять же это хорошо разжевано но уже у basecamp в их getting real хотя конечно их подход не всех устраивает, но зато он предельно простой.
0
springimport ,   * (был изменён)
клонирование занимает больше 10-20 минут
проект индексируется в Intellij IDEA от 30 до 40 минут

Очень интересно. Я работаю с magento 2 и всегда думал что это сверхтяжелый проект с десятками тысяч файлов. Клонирование не занимает больше 1 минуты, индексация в phpsotrm менее 30 секунд.
Можно узнать сколько у вас сотен тысяч файлов? Каков ваш конфиг рабочего компьютера?
0
gecube ,  
10 тысяч — это фигня.
Был момент, когда утекли исходники NT4 и Windows 2000. Ядро и user space. Написано на С, местами С++.
Ес-но, что любая IDE давится такой кодовой базой. Сложно сказать сейчас статистику по файлам, но явно есть совершенно разные требования по разбору разных языков.
0
kanu ,  
У нас Typescript + Java :)
Конфиг хороший — МакБук Про.
0
springimport ,   * (был изменён)
Посмешили)) Макбук про даже последних версий мягко говоря отдыхает по сравнению с десктопными процессорами, не говоря уже про hedt с 12/16-ядерными тредриперами.
На счет typescript все понял, буду 2 раза думать если буду выбирать)
0
flashmozzg ,  
Проблему с долгом клонированием можно будет решить с помощью partial clone: git-scm.com/docs/partial-clone
0
kanu ,  
Зачем ее решать, если можно не решать?
И скорее всего мне нужен весь репозиторий (ведь если он весь собирается одним билд тулом), а не его часть
0
gecube ,  

Есть еще git clone --depth 1, но он тоже не решает проблему системно.

0
flashmozzg ,  
Когда размеры репозитория переваливают за десятки гигабайт, то локально вы всё равно вряд ли что-нибудь соберёте за разумное время. В организациях работающих с такими большими кодовыми базами обычно вся сборка, тестирования и т.п. идёт на выделенных серверах. Вот у них может быть весь репозиторий, а разработчики достаточно только части, над которой он работает.
+1
kanu ,   * (был изменён)
Вот, например еще мнение:
mastodon.technology/@robey/101349183169527275
0
PavelGatilov ,  
Согласен. Без всех тулзов и что немаловажно — средств, монорепо выглядит как глупая затея. Для монорепо нужнее как минимум очень стабильный и быстрый CI.