Выбор между одним или несколькими проектами в репозитории git?

223

В gitсреде, где мы модульно структурировали большинство проектов, мы сталкиваемся с одним проектом на репозиторий или несколькими проектами на проектирование репозитория . Давайте рассмотрим модульный проект:

myProject/
   +-- gui
   +-- core
   +-- api
   +-- implA
   +-- implB

Сегодня у нас есть один проект на репозиторий . Это дает свободу

  • release отдельные компоненты
  • tag отдельные компоненты

Но это также неудобно для branchкомпонентов, так как часто для ветвления apiтребуются эквивалентные ветви coreи, возможно, другие компоненты.

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

Какой опыт есть и как / почему вы решили эти проблемы?

Йохан Шёберг
источник
1
У меня сейчас очень похожая проблема. Мне нужно выпустить разные версии проекта, поэтому они должны быть в разных репозиториях. Это кошмар, чтобы управлять, хотя. Было бы здорово, если бы был способ разветвлять только подкаталоги.
Эндрю Финнелл
1
Каждый модуль должен иметь отдельные номера версий. И мы используем git-describe.
Linquize
stackoverflow.com/a/29665889
Джоэл Пурра
Я удивлен, что Бит ( bitsrc.io ) и Лерна ( github.com/lerna/lerna ) не упоминаются! Вы можете узнать больше здесь: hackernoon.com/...
Йони

Ответы:

199

Есть три основных недостатка one project per repository, как вы описали выше. Это менее верно, если они действительно разные проекты, но, судя по звукам, изменения одного часто требуют изменений другого, что действительно может усугубить эти проблемы:

  1. Сложнее обнаружить, когда появились ошибки. Такие инструменты git bisectстановятся намного сложнее в использовании, когда вы разбиваете свой репозиторий на суб-репозитории. Это возможно, просто это не так просто, а значит, охота на багов во времена кризиса намного сложнее.
  2. Отслеживание всей истории объекта намного сложнее. Команды обхода истории, такие как git logпросто, не выводят историю так же осмысленно со сломанными структурами хранилища. Вы можете получить полезный вывод с помощью подмодулей или поддеревьев, или с помощью других скриптовых методов, но это не то же самое, что печатать tig --grep=<caseID>или git log --grep=<caseID>сканировать все коммиты, которые вас интересуют. Вашу историю становится сложнее понять, что делает ее менее полезной, когда она вам действительно нужна.
  3. Новые разработчики тратят больше времени на изучение структуры контроля версий, прежде чем они смогут начать кодирование. Каждое новое задание требует выбора процедур, но разрушение репозитория проекта означает, что они должны выбрать структуру VC в дополнение к архитектуре кода. По моему опыту, это особенно трудно для начинающих разработчиков, которые приходят из более традиционных централизованных магазинов, которые используют один репозиторий.

В конце концов, это расчет альтернативной стоимости. У одного бывшего работодателя наше основное приложение было разделено на 35 различных подпозиториев. Вдобавок к этому мы использовали сложный набор сценариев для поиска в истории, чтобы убедиться, что состояние (т.е. ветви производства и разработки) были одинаковыми во всех них, и развернуть их по отдельности или в массовом порядке.

Это было просто слишком много; слишком много для нас, по крайней мере. Затраты на управление сделали наши функции менее гибкими, значительно усложнили развертывание, заставили обучение новых разработчиков занимать слишком много времени, и к концу этого времени мы едва могли вспомнить, почему мы изначально сломали хранилище. В один прекрасный весенний день я потратил 10 долларов на полдень времени кластерных вычислений в EC2. Я сплел репо вместе с парой дюжин git filter-branchзвонков. Мы никогда не оглядывались назад.

Кристофер
источник
7
Не говоря уже о том, что в качестве менеджера хранилища есть несколько более приятных вещей, чем покупка времени в системе, которая за два часа может сделать то же, что и ваш ноутбук, а за 20 - дешевле, чем за обед. Иногда я действительно люблю интернет.
Кристофер
2
Как бы вы выпустили эти отдельные проекты как отдельные выпуски? Или тебе никогда не нужно этого делать? Это проблема, которая у меня есть. С, если вам нужно создать V1 проекта A и V2 проекта B.
Эндрю Т Финнелл
5
Для перехода между «один проект на репо» и «несколько репо» рассмотрите git-subtree (хорошее объяснение на stackoverflow.com/a/17864475/15585 )
отмена
1
Я написал скрипт для автоматизации этого для общих случаев использования: github.com/Oakleon/git-join-repos
chrishiestand
Что такое "структура ВК"?
Роберт Харви
60

Кристофер очень хорошо перечислил недостатки модели «один проект на репозиторий». Я хотел бы обсудить некоторые причины, по которым вы могли бы рассмотреть подход с несколькими хранилищами. Во многих средах, в которых я работал, подход с несколькими репозиториями был разумным решением, но решение о том, сколько репозиториев иметь и где делать сокращения, не всегда было легко сделать.

На моей нынешней должности я перенес гигантский CVS-репозиторий с одним репозиторием с более чем десятилетней историей в ряд git-репозиториев. После этого первоначального решения количество хранилищ выросло (благодаря действиям других команд), и я подозреваю, что у нас их больше, чем было бы оптимальным. Некоторые новички предложили объединить репозитории, но я выступил против этого. Проект Wayland имеет аналогичный опыт. В одном из выступлений, которые я видел недавно, у них было более 200 репозиториев git, за которые ведущий извинился. Глядя на их сайт , я вижу, что сейчас они на 5, что кажется разумным. Важно отметить, что объединение и разделение репозиториев - это управляемая задача, и с ней можно экспериментировать (в пределах разумного).

Так когда же вы захотите несколько хранилищ?

  1. Один репозиторий будет слишком большим, чтобы быть эффективным.
  2. Ваши репозитории слабо связаны или отделены.
  3. Разработчику обычно нужен только один или небольшое подмножество ваших репозиториев для разработки.
  4. Обычно вы хотите разрабатывать репозитории независимо друг от друга, и вам нужно только синхронизировать их время от времени.
  5. Вы хотите поощрить больше модульности.
  6. В разных хранилищах работают разные команды.

Точки 2 и 3 имеют значение только в том случае, если точка 1 верна. Разделив наши репозитории, я значительно сократил задержки, с которыми сталкиваются наши сторонние коллеги, уменьшил потребление диска и улучшил сетевой трафик.

4 и 5 более тонкие. Когда вы разделяете репозитории, скажем, клиент и сервер, это делает более дорогостоящим координацию изменений между кодом клиента и сервера. Это может быть позитивным, поскольку поощряет разделение интерфейса между ними.

Даже с недостатками проектов с несколькими хранилищами, таким образом проделана большая респектабельная работа - на ум приходят Wayland и Boost. Я не верю, что консенсус относительно лучших практик еще не выработан, и требуется определенное суждение. Инструменты для работы с несколькими репозиториями (git-subtree, git-submodule и другие) все еще находятся в стадии разработки и экспериментов. Мой совет - экспериментировать и быть прагматичным.

Spacemoose
источник
7
Этот ответ был бы еще более полезен со ссылкой, подтверждающей утверждение: «объединение и разделение репозиториев - управляемая задача».
Wildcard
3
Многократные репозитории могут также работать против модульности, потому что они затрудняют изменение общего кода. Зависимости перекрестного репо усложняют интеграцию, могут легче взломать код (даже если у вас есть хороший инструмент для проверки этого), а угроза взлома кода из репо препятствует рефакторингу интерфейсов, который является одним из ваших самых мощных инструментов для создания вещей. более модульный.
Курт Дж. Сэмпсон
Все о MicroServices и дизайне DDD хранится здесь. Вы должны минимизировать общий код.
Арвин
49

Поскольку мы используем GitHub, у нас фактически есть несколько проектов в одном репо, но мы гарантируем, что эти проекты / модули должным образом модулированы (мы используем соглашения -api и -core + Maven + статическая проверка и проверка во время выполнения и даже могли бы однажды перейти на OSGi для загрузки) ,

На чем это экономит? Что ж, нам не нужно выдавать несколько запросов на извлечение, если мы меняем что-то маленькое в нескольких проектах. Вопросы и вики хранятся централизованно и т. Д.

Мы по-прежнему рассматриваем каждый модуль / проект как самостоятельный независимый проект, а также строим и интегрируем их отдельно в наш CI-сервер и т. Д.

Мартейн Вербург
источник
1
Очень интересно. Я подозреваю, что это обычная модель на github. Если вы сталкиваетесь с отдельными выпусками компонентов, используете ли вы что-то вроде submodulesили выпускаете / помечаете весь репозиторий?
Йохан Шёберг
субмодули, если мы должны, но пока мы версии от родителя вниз.
Мартейн Вербург
У моего нынешнего работодателя мы используем похожую стратегию и упаковываем метаданные о самом последнем коммите в проекте в различные файлы манифестов артефактов (то есть результаты git log -1 -- <project_dir>). Это действительно здорово. Этот ответ заслуживает большего количества голосов.
Кристофер
22

Для меня основным отличием в использовании одного или нескольких репозиториев являются ответы на следующие вопросы:

  • У нескольких частей, разработанных одной и той же командой, одинаковый цикл выпуска, один и тот же клиент? Тогда есть меньше причин для разделения одного хранилища.
  • Многочисленные части сильно зависят друг от друга? Таким образом, разделение модели, контроллера и пользовательского интерфейса (даже если они являются разными частями) не очень разумно из-за высокой зависимости друг от друга. Но если 2 части имеют небольшую зависимость, которая реализуется стабильным интерфейсом, который меняется только каждые несколько лет, то было бы разумно разделить 2 части на 2 репозитория.

Например, у меня есть небольшое приложение (только клиент), которое проверяет «качество» хранилища Subversion. Существует базовая реализация, которую можно запустить из командной строки, и она хорошо работает с Java 6. Но я начал реализовывать пользовательский интерфейс, который использует JavaFX как часть Java 8. Поэтому я разделил 2 и создал второй репозиторий (со вторым процессом сборки), с другим расписанием, ...

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

mliebelt
источник
0

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

Теперь, на мой взгляд, пользовательский интерфейс должен быть независимым от серверной части. Таким образом, репозиторий проекта пользовательского интерфейса обычно должен содержать код пользовательского интерфейса и контроллер клиента. Клиентский контроллер будет соединяться с сервисными контроллерами абстрактно. Они будут использовать сервисную абстракцию client / api, которая имеет версии отдельно от сервиса, так что сервис может быть обновлен, не нарушая клиент (ы) (может быть несколько разных клиентов).

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

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

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

Arwin
источник