Вибір одного або декількох проектів у сховищі git?


223

У gitсередовищі, де ми модулювали більшість проектів, ми стикаємося з одним проектом на сховище або декількома проектами на кожну проблему дизайну сховища . Розглянемо модульований проект:

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

Сьогодні у нас є один проект на сховище . Це дає свободу

  • release окремі компоненти
  • tag окремі компоненти

Але це також громіздко до branchкомпонентів, оскільки часто розгалуження apiвимагає еквівалентних гілок у core, можливо, інших компонентів.

Враховуючи, що ми хочемо до releaseокремих компонентів, чи можемо ми все-таки отримати подібну гнучкість, використовуючи кілька проектів на дизайн сховища .

Який досвід є і як / чому ви вирішили ці питання?


1
У мене зараз дуже схоже питання. Мені потрібно випустити різні версії проекту, тому вони знадобляться у різних сховищах. Це кошмар, яким можна керувати. Було б чудово, якби був спосіб розгалуження лише підкаталогів.
Ендрю Т Фіннелл

1
Кожен модуль повинен мати окремі номери версій. І ми використовуємо git-describe.
зв’язати



Я здивований, побачивши, що Біт ( bitsrc.io ) та Лерна ( github.com/lerna/lerna ) не згадуються! Ви можете дізнатися більше тут: hackernoon.com/…
Yoni

Відповіді:


199

Є три основні недоліки one project per repository, як описано вище. Вони менш вірні, якщо вони є справді окремими проектами, але від звуку цього зміни для одного часто потрібні зміни до іншого, що може справді перебільшувати ці проблеми:

  1. Важче виявити, коли були введені помилки. Такі інструменти, як наприклад, git bisectстає набагато складніше використовувати, коли ви розбиваєте своє сховище на підпозиції. Це можливо, це не так просто, значить, полювання на клопів у кризові періоди набагато складніше.
  2. Відстежувати всю історію функції набагато складніше. Команди переходу історії, як-от git logпросто, не виводять історію так значимо з розбитими структурами сховища. Ви можете отримати корисний вихід із підмодулями чи підрядками, або за допомогою інших методів написання сценарію, але це просто не те, що набирати tig --grep=<caseID>чи git log --grep=<caseID>сканувати всі необхідні вами зобов'язання. Вашу історію стає важче зрозуміти, що робить її менш корисною, коли вона вам справді потрібна.
  3. Нові розробники витрачають більше часу на вивчення структури версій, перш ніж вони зможуть розпочати кодування. Кожне нове завдання вимагає підбору процедур, але розбиття сховища проектів означає, що вони повинні підбирати структуру VC на додаток до архітектури коду. З мого досвіду, це особливо важко для розробників, новичків з git, які приїжджають із більш традиційних, централізованих магазинів, які використовують єдине сховище.

Зрештою, це можливий розрахунок витрат. У одного колишнього роботодавця основну заявку ми розділили на 35 різних підрепозиторіїв. Зверху на них ми використовували складний набір сценаріїв для пошуку історії, переконайтесь, що стан (тобто виробництво порівняно з галузями розвитку) був однаковим для них, і розгортати їх окремо або масово.

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


7
Крім поза темою, є кілька приємніших речей як менеджера сховищ, ніж придбання часу в системі, яка може за дві години зробити те, що ваш ноутбук не міг зробити за 20, за меншу ціну на обід. Іноді я дуже люблю Інтернет.
Крістофер

2
Як би ви випустили ці окремі проекти як окремі випуски? Або вам ніколи цього не потрібно робити? Це проблема, яка в мене є. Якщо вам потрібно створити V1 проекту A та V2 проекту B.
Ендрю Т Фіннелл

5
Для переміщення між «одного проекту на репо» і «декількох» РЕПО розглянути ГИТ-поддерево (гарне пояснення в stackoverflow.com/a/17864475/15585 )
deterb

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 та інші) все ще розробляються та експериментуються. Моя порада - експериментувати та бути прагматичним.


7
Ця відповідь була б ще кориснішою з посиланням на підтвердження твердження: "приєднання та розділення сховищ - це керована задача".
Wildcard

3
Кілька репостів також можуть працювати проти модульності, оскільки вони ускладнюють зміну спільного коду. Перехресні залежності репо роблять інтеграцію складнішою, можуть зрушити код легше (навіть якщо у вас є гарний інструмент для перевірки цього) та загроза виходу з ладу коду репо перешкоджає переробленню інтерфейсів, що є одним з ваших найпотужніших інструментів для створення справ більш модульний.
Керт Дж. Сампсон

Тут є все, що стосується дизайну MicroServices та DDD. Ви повинні мінімізувати спільний код.
Арвін

49

Оскільки ми використовуємо GitHub, ми фактично маємо декілька проектів за один репо, але гарантуємо, що ці проекти / модулі належним чином модулюються (ми використовуємо -api та -core конвенції + Maven + статичну перевірку та час виконання та навіть можемо один день перейти до OSGi для завантаження) .

На чому це економить? Ну, нам не потрібно видавати кілька запитів на витяг, якщо ми змінюємо щось невелике в кількох проектах. Випуски та Wiki зберігаються централізовано тощо.

Ми все ще розглядаємо кожен модуль / проект як належний незалежний проект і будуємо та інтегруємо їх окремо в наш сервер CI тощо.


1
Дуже цікаво. Я б підозрював, що це звичайна модель на github. Якщо ви стикаєтесь з окремими випусками компонентів, чи використовуєте ви щось на кшталт submodulesабо випускаєте / тегуєте весь сховище?
Йохан Шьоберг

підмодулі, якщо нам доведеться, але наразі ми версію від батьківського вниз.
Мартійн Вербург

У мого нинішнього роботодавця ми використовуємо аналогічну стратегію та пакуємо метадані про останню фіксацію у проекті різних файлів артефактів (тобто результатів git log -1 -- <project_dir>). Це дійсно досить чудово. Ця відповідь заслуговує на більшу кількість відгуків.
Крістофер

22

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

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

Як приклад, у мене є невелика програма (лише клієнт), яка перевіряє "якість" сховища Subversion. Є основна реалізація, яку можна запустити з командного рядка і добре працює з Java 6. Але я почав реалізовувати інтерфейс користувача, який використовує JavaFX як частину Java 8. Отже, я розділив 2, і створив друге сховище (з другим процесом збирання), з різним графіком, ...

Мені подобаються відповіді вище (проголосували їх), але я думаю, що це не вся справжня історія. Тому я хотів додати аргументи і для розділення сховищ. Тож справжня відповідь (коли потрібно розділити) може бути десь посередині ...



0

З вашого прикладу, сховища повинні бути налаштовані з точки зору їх взаємозалежності. Усі міркування щодо розробки дизайну MicroServices і керованого доменом застосовуються тут: у деяких випадках прийнятний дублікат коду, робота з інтерфейсами, не порушуйте сумісність, якщо вам це не потрібно і т.д.

На мою думку, інтерфейс повинен бути незалежним від бекенда. Таким чином, сховище проектів інтерфейсу повинно містити код інтерфейсу та контролер клієнта. Клієнтський контролер зв’яжеться з сервісними контролерами абстрактно. Вони використовуватимуть сервіс-клієнт / api абстракцію, який розроблений окремо від служби, щоб послугу можна було оновити, не порушуючи клієнтів (може бути декілька різних клієнтів).

Отже, сервіс сам повинен бути власним сховищем. На мою думку, сервіс - це лише обгортка певної логіки бізнесу, що відповідає одній точці. Тож бізнес-логіка зазвичай повинна бути окремою від сервісної технології, яка її розміщує. З іншого боку, реалізація сховища, як правило, настільки тісно пов'язана з бізнес-логікою, що це може бути інтегровано в одному сховищі. Але навіть там ваш пробіг може відрізнятися.

Звичайно, прості проекти, які навряд чи сильно зміняться з точки зору технології або підтримки декількох стеків, де весь інтерфейс користувача може розміщуватися з того самого джерела, що і бекенд, і сервіси бекенда, як правило, використовуються лише тим самим клієнтом, можуть отримати більше переваг щільно інтегровані сховища.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.