Комментарии 42
Не увидел в статье ссылки на репозиторий.
Это репозиторий с git. Хотелось бы видеть https://github.com/Microsoft/Windows/, о котором шла речь в статье.
До перехода на Git мы пользовались Source Depot и код был распределен по 40 с лишним репозиториям
Не очень понятно почему бы не продолжать делать также — разбить на изолированные независимые модули и работать с ними также независимо. Зачем хранить исходники всей системы (видимо даже солитер там) в одном репозитории?
Похоже, ребята из Microsoft не до конца разобрались с тем, как этим пользоваться. Или, возможно, их код страдает от сильной связности, поэтому нельзя сделать какие-то изменения только в одном компоненте — нужно делать pull request в сотне репозиториев одновременно, а это неудобно и приводит к ошибкам.
Ну я не претендую на то, чтобы быть истиной в последней инстанции. Мне казалось, что разбиение на множество мелких репозиториев имеет те же преимущества, что и микросервисная архитектура — между микропроектами получаются жесткие контракты, и говнокод каждого микропроекта изолирован, что позволяет заменять реализации чуть ли не на ходу, до тех пор, пока контракт выполняется.
Если хранить все в одном гигантском репозитории… я не знаю, я не могу придумать плюсов такому решению. То, что предлагается как плюсы в гугловском документе, мне кажется достаточно надуманным:
Unified versioning, one source of truth;
Зачем? Какой профит в "единой версии всего", особенно когда поменялась, грубо говоря, версия солитера, но это вынуждает глобальную систему бампнуть версию? Как отслеживать версию такого проекта согласно семантическому версионированию, когда у меня произошел breaking change в солитере, но это никак не влияет на другие части системы?
Extensive code sharing and reuse;
Что мешает реюзать код в распределенном окружении? Если какой-то код используется в двух проектах, то он должен быть вынесен в библиотеку, а не скопирован. У этой библиотеки свой репозиторий, своя версия, свои зависимости.
Simplified dependency management;
Я понимаю, к чему это — вместо того, чтобы перечислять зависимости явно, там, скорее всего, здоровенный список "давайте любой код будет зависеть от libcommon, в которую включено все, что у нас только есть". Хороший ли это подход? Я думаю, это омерзительный подход, так как в libcommon вносятся несовместимые изменения, то как узнать, что именно нужно чинить?
Atomic changes;
Единственное "достоинство". В распределенных системах надо сначала поменять базовую зависимость, протестировать ее, затем поменять тех, кто зависит от базовой зависимости, и т.д. Впрочем, минусы этого решения покрывают возможный плюс, как мне кажется.
Large-scale refactoring;
Для этого и существуют контракты между разными компонентами. Если есть контракт, возможно автоматически или полуавтоматически определить, где проходит общая граница ответственности — т.е. какие именно компоненты можно буквально слить воедино, а потом переразбить иначе, с другой реализацией, так, чтобы для "внешнего мира" их зависимости все еще были валидны.
Collaboration across teams;
Flexible team boundaries and code ownership;
Это не является достоинством монорепозитория. Отдельными репозиториями легче управлять, в том числе разделяя права доступа, и легче определить, кто что сломал. Не говоря уже о том, что список веток в микрорепозитории может быть небольшим и управляемым, а вот что делать с миллиардом веток в монорепозитории, в котором любой Джон Иванов, начиная работу над своей фичей, создаст себе ветку? Не пушить их? Пушить их в отдельный origin, в котором есть не все ветки?
Code visibility and clear tree structure providing implicit team namespacing.
Тут мне на ум приходит только цитата Гвидо ван Россума, одного из сотрудников Гугл — Explicit is better than implicit. Simple is better than complex. Flat is better than nested. Sparse is better than dense.. Если деление на команды все равно происходит неявно на уровне структуры репозитория, зачем делать это одним репозиторием, когда это УЖЕ логически разделяет репозиторий на подрепозитории?
Так много вопросов, так мало ответов.
Я бы не стал просто потому, что мало ответов, считать себя умным, а Google, Facebook и Microsoft идиотами, не понимающими, что они делают. У вас есть личный опыт работы с действительно большими репозитариями, чтобы вы могли судить, что работает на таких объемах, а что нет?
Понимаю, "сперва добейся". Нет, очевидно, у меня нет опыта работы с репозиториями размера кодобазы Microsoft, поэтому это автоматически лишает меня права задавать вопросы и высказывать мнение. Извините, пожалуйста, я больше так не буду.
Не "сперва добейся", а "сперва разберись".
Здесь ведь Хабр, а не лавочка у дома. Вы не работали с большими репозитариями, не знаете, какие проблемы могут возникнуть в процессе, но уже обвинили людей, которые работали и решали соответствующие проблемы в том, что они "не разобрались". Я бы сказал, что для этого нужно основание. Причем факт, что таких людей (читай, компаний) не одна, а несколько, вашу критику никак не остановил. Как и тот факт, что это крупнейшие ИТ-компании в мире с умнейшими людьми в штате и менеджменте.
Я согласен — раз уж умнейшие люди из крупнейших IT-компаний приняли такое решение, то мои вопросы автоматически стали глупыми и непрофессиональными. Наверняка ответ есть, дорасту — узнаю.
Грубо говоря выгода от одного репозитория уже менее очевидна, так как может быть куча разных версий и они могут быть друг с другом не связаны. Можно сказать это выглядит как разработка абсолютно разных приложений и не всегда имеет смысл запихивать в один репозиторий, как раз из-за проблем описанных в статье.
Мне казалось, что разбиение на множество мелких репозиториев имеет те же преимущества, что и микросервисная архитектура — между микропроектами получаются жесткие контракты, и говнокод каждого микропроекта изолирован, что позволяет заменять реализации чуть ли не на ходу, до тех пор, пока контракт выполняется.Вы абсолютно правы — но смотрите на медаль только с одной стороны.
Вот собственно в этом «пока контракт выполняется» — и есть главная проблема. В случае с монорепозиторием вы можете поменять в любой момент всё, что угодно — в том числе и контракт между компонентами. Собственно это не изобретение Microsoft'а, Facebook'а или Google'а. Классическое Stable API nonsense всё описывает…
Как отслеживать версию такого проекта согласно семантическому версионированию, когда у меня произошел breaking change в солитере, но это никак не влияет на другие части системы?А зачем? Если вы код никому не поставляете и не релизите? Сделаете релиз — увеличите счётчик…
Я понимаю, к чему это — вместо того, чтобы перечислять зависимости явно, там, скорее всего, здоровенный список «давайте любой код будет зависеть от libcommon, в которую включено все, что у нас только есть».Ровно наоборот. Если вы обнаружили, что у вас вдруг завелась библиотека, которая и стрижёт кошечек и запускает ракеты в космос, то вы её можете извести, условно говоря, в два commit'а: первый выносит функциональность по стрижке кошечек в libcathaircut и одновременно изменяет всех клиентов, второй — делает то же с библиотекой libspacelaunch. Всё. После двух коммитов у вас библиотеки libcommon больше нету.
На практике, конечно, стараются коммиты делать меняющими не сто тысяч файлов за раз, а несколько меньшее число, так что совсем уж мастабный рефакторинг в два коммита не уложится — но идея понятна, я думаю.
libbase, конечно, тоже есть — но там живут вещи, которые реально нужны всем (система выдачи сообщений об ошибках, к примеру).
В распределенных системах надо сначала поменять базовую зависимость, протестировать ее, затем поменять тех, кто зависит от базовой зависимости, и т.д. Впрочем, минусы этого решения покрывают возможный плюс, как мне кажется.Это зависит от того, что вы, собственно, пытаетесть сделать. Минус — более-менее один, но он существенен: «подход с поменять базовую зависимость, протестировать ее, затем поменять тех, кто зависит от базовой зависимости, и т.д.» занимает на два порядка больше времени. То есть какое-нибудь простое измнение (типа переименования поля в структуре с «childs» на «children») занимает годы, а не часы.
Если есть контракт, возможно автоматически или полуавтоматически определить, где проходит общая граница ответственности — т.е. какие именно компоненты можно буквально слить воедино, а потом переразбить иначе, с другой реализацией, так, чтобы для «внешнего мира» их зависимости все еще были валидны.А что происходт в случае изменения контракта?
Не говоря уже о том, что список веток в микрорепозитории может быть небольшим и управляемым, а вот что делать с миллиардом веток в монорепозитории, в котором любой Джон Иванов, начиная работу над своей фичей, создаст себе ветку?Откуда там миллиарды веток? Любой Джон Иванов может насоздавать себе локально сколько угодно веток, но когда он свои изменения зальёт — он будет их заливать в те ветки, которые соответствуют «мастеру» и, возможно, их «заберут» в старые релизы, если нужно.
Единственное "достоинство"
Это большое достоинство, очень хорошее. Приходилось работать с системой, которая состояла из десятков пакетов, которые нужно собирать и релизить независимо. Каждый раз, когда нужно протащить что-то через 2-3 компонента, разработка превращается в головную боль, протестировать всё вместе очень сложно.
С монорепозиторием жизнь несравнимо легче. Все обладатели нетривиальной кодовой базы, которая быстро развивается, рано или поздно приходят к монорепозиторию.
Large-scale refactoring
Для этого и существуют контракты между разными компонентами
Тут не только контрактах речь. Допустим, вы решили заменить во всей кодовой базе NULL на nullptr. С кучей мелких репозиториев это настолько большая морока, что никто просто не будет этим заниматься. С монорепозиторием это тривиально.
Далее, если вдруг хочется избавиться от какого-то компонента, всех его пользователей найти тривиально, можно использовать привычные инструменты, при этом исправление будет атомарным. Если этот компонент лежит в отдельном репозитории, найти (и поправить) всех его пользователей гораздо сложнее.
Simplified dependency management;
Я понимаю, к чему это
вместо того, чтобы перечислять зависимости явно
Наоборот, с монорепозиторием гораздо проще делать явные списки зависимостей. Хочешь сделать либу: положи код в каталог, создай зависимость в билд-системе. Любой сможет её найти. Настройка отдельного репозитория и настройка интеграции с ним сложнее. Опять же, нужно сделать что-то, чтобы другие разработчики смогли найти и использовать ваш код.
Когда репозиториев много, соблазн просто скопировать нужный код к себе гораздо сильнее.
Посмотрите хотя бы на vendoring в Go-community.
Гвидо ван Россума, одного из сотрудников Гугл
Он давно уже в Dropbox работает
Зачем хранить исходники всей системы (видимо даже солитер там) в одном репозитории?
Масштабирование Git (и кое-какая предыстория)
Когда-нибудь работали с огромной кодовой базой в течение 20 лет? Когда-нибудь пробовали впоследствии вернуться назад и разбить её на маленькие репозитории? Можете догадаться, к какому ответу мы пришли. Этот код очень сложно разобрать на части. Цена будет слишком велика. Риски от такого уровня смешения станут чудовищными.
Грубо говоря, что если солитеру нужно использовать 10 фич новой сетевой библиотеки которая находится на этапе написания и разработка должна идти параллельно чтобы успеть к релизу? А сетевая библиотека требует 10 других зависимостей которые также находятся в процессе.
если солитеру нужно использовать 10 фич новой сетевой библиотекиСолитер с мультиплеером? Прошу прощения, что придираюсь, мысль ваша, конечно, понятна.
Правда, на данный момент это отдельные приложения устанавливаемые через Microsoft Store, и я не понял, такие приложения тоже в общем большом репозитории или всё-таки отдельно?
70 секунд против 25 минут — это улучшение почти на 95%
В 21 раз или это ошибка?
Взгляд инсайдера (моего друга, которы работал на Марсе в компании Deep Startup Mining Inc.): монолитный репозиторий ужасно неудобно использовать. Тормозит любая комманда, кроме git commit
и ещё парочки ничего толком нельзя использовать. Вся работа с репозиторием, в основном, происходит через внутренние веб-инструменты. Понимают ли люди, отвечающие за VCS, что они делают? Абсолютно. Просто их задача не сделать работу программистов комфортнее, а снизить число факапов. Один из примеров использования монолитного репозитория — если случился факап, репозиторий быстро откатывается на последнюю стабильную версию. И нет проблем с зависимостями или ещё чем-то. А программистов никто не спрашивает "а не хотите ли заиметь один репозиторий, чтобы править ими всеми, судари?", их просто ставят перед фактом.
Или все разрабы, даже самые мелкие, имеют доступ ко всему коду всех остальных разработчиков?
Очень советую всем попробовать http://pijul.com/
Куда проще и логичнее чем GIT который у меня ничего кроме неприязни не вызывает.
Так они и рассказывали, что GVFS и есть смесь TFS и Git. Почитайте первую статью
Самый большой репозиторий Git на свете