Організація сховищ Git із загальними вкладеними підмодулями


50

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

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

Припустимо пару програм: studioі player, і залежних бібліотек core, graphі network, де залежності такі:

  • core є автономним
  • graphзалежить від core(підмодуль в ./libs/core)
  • networkзалежно від core(підмодуль в ./libs/core)
  • studioзалежить від graphта network(підмодулі в ./libs/graphі ./libs/network)
  • playerзалежить від graphта network(підмодулі в ./libs/graphі ./libs/network)

Припустимо, що ми використовуємо CMake і що кожен із цих проектів має одиничні тести та всі роботи. Кожен проект (включаючи studioта player) повинен мати можливість складати окремо для виконання показників коду, тестування одиниць тощо.

Річ у тому, що рекурсивна git submodule fetch, тоді ви отримуєте таку структуру каталогу:

studio/
studio/libs/                    (sub-module depth: 1)
studio/libs/graph/
studio/libs/graph/libs/         (sub-module depth: 2)
studio/libs/graph/libs/core/
studio/libs/network/
studio/libs/network/libs/       (sub-module depth: 2)
studio/libs/network/libs/core/

Зауважте, що coreв studioпроекті клонували двічі . Окрім цього витраченого місця на диску, у мене є системна проблема складання, оскільки я будую coreдвічі і, можливо, я отримую дві різні версії core.

Питання

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

Можливе рішення

Якщо залежність бібліотеки є якоюсь пропозицією (тобто у моді «відомо, що працює з версією X» або «тільки версія X офіційно підтримується») і потенційні залежні програми або бібліотеки відповідають за створення будь-якої версії, яка їм подобається, тоді Я міг би уявити такий сценарій:

  • Запропонуйте систему побудови graphта networkскажіть, де їх знайти core(наприклад, через компілятор включити шлях). Визначте дві цілі побудови, "окрему" та "залежність", де "автономна" базується на "залежності" і додає шлях включення для вказівки на локальний coreпідмодуль.
  • Введіть додаткову залежність: studioвід core. Потім, studioбудує core, встановлює шлях включення до власної копії coreпідмодуля, потім будує graphі networkв режимі "залежності".

Отримана структура папки виглядає так:

studio/
studio/libs/                    (sub-module depth: 1)
studio/libs/core/
studio/libs/graph/
studio/libs/graph/libs/         (empty folder, sub-modules not fetched)
studio/libs/network/
studio/libs/network/libs/       (empty folder, sub-modules not fetched)

Однак для цього потрібна якась системна магія (я впевнений, що це можна зробити за допомогою CMake) та трохи ручної роботи над оновленням версій (оновлення graphтакож може потребувати оновлення coreта networkотримання сумісної версії coreу всіх проектах) .

Будь-які думки з цього приводу?


Зауважте, що ця проблема не характерна для cmake: вона існує для будь-якої системи складання, включаючи жодної системи! (Тобто , коли він призначений , що супер-проект просто додати джерела бібліотеки, яка включає в себе заголовок тільки бібліотеки)
MM

Відповіді:


5

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

У мене точно така ж проблема з C ++ / CMake / Git / Submodules, і у мене є аналогічна проблема з MATLAB / Git / Submodules, яка отримує певну дивність, оскільки MATLAB не компілюється. Нещодавно я натрапив на це відео , яке, здається, пропонує "рішення". Мені не подобається рішення, оскільки воно по суті означає викидання субмодулів, але це усуває проблему. Це так, як рекомендує @errordeveloper. У кожному проекті немає підмодулів. Щоб побудувати проект, створіть суперпроект для його побудови та включіть його як рідного брата до його залежностей.

Тож ваш проект для розробки graphможе виглядати так:

buildgraph/graph
buildgraph/core

і тоді ваш проект для студії може бути:

buildstudio/studio
buildstudio/graph
buildstudio/network
buildstudio/core

Суперпроекти - це лише основна CMakeLists.txtі купа підмодулів. Але жоден з проектів не має самих підмодулів.

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


1

Я припускаю, що при інтеграції обох graphта networkпідмодулів у історію studioви завжди повинні мати одну і ту ж версію . Я би спростив підмодуль в .corestudiostudio/libs/corestudio/libs/{graph,network}/libs

Оновлення:

Я створив декілька сховищ із залежностями, які ви вказали:

./core      <--- (v2)
./graph
./graph/libs
./graph/libs/core  <--- (v2)
./graph/.gitmodules
./network
./network/libs
./network/libs/core  <--- (v1)
./network/.gitmodules
./studio
./studio/libs
./studio/libs/graph
./studio/libs/graph/libs
./studio/libs/graph/libs/core <--- (v1)
./studio/libs/graph/.gitmodules
./studio/libs/network
./studio/libs/network/libs
./studio/libs/network/libs/core  <--- (v1)
./studio/libs/network/.gitmodules
./studio/studio
./studio/.gitmodules

v1і v2це дві різні версії core. graphобробляє версію 2, тоді як networkпотрібна певна робота і застрягла у версії 1. У studioлокальні вбудовані версії coreобох точок v1, щоб мати робочу програму. Тепер, крім перспективи збірки, все добре працює з підмодулями.

Тепер я можу видалити наступний каталог:

./studio/libs/network/libs/core

І замініть його символічним посиланням:

./studio/libs/network/libs/core@ -> ../../graph/libs/core/

Я здійснюю локально цю зміну і втрачаю можливість мати дві окремі версії coreвсередині studio, але будую лише coreодин раз. Коли я готовий до оновлення v2, я можу:

 git submodule update # (--rebase ?)

... всередині студії / libs / мережі.


Ідея символічного зв’язку перехрестила мене, але це не рішення. Якщо ви посилаєтесь graph/libs/coreназовні, ви не використовуєте підмодуль. Якщо ви посилаєтесь studio/libs/coreна одну з власних бібліотек підмодуля, то яку саме ви обираєте, graphабо network? Більше того, що відбувається, коли це три або більше шарів глибоко? Нарешті, що робити, якщо coreможе бути ряд змін. Це не очевидно , що ви хочете зробити посилання на будь-яку версію , coreщо graphі networkвикористовуєте.
Андре Карон

"який ви обираєте?" : coreбуде підмодулем, отриманим з оригінальної coreбібліотеки, оновленим до версії, сумісної обох graphі network(ви повинні вирішити, який із них хороший). Символічні посилання будуть додані в локальні graphта networkпідмодулі (незавершені).
coredump

1
Символічні посилання, які ви пропонуєте додати graphі networkвказуватимуть за межами власного сховища (наприклад, десь ще в studioпроекті). Як вони знають, коли використовувати власний підмодуль проти того, коли використовувати символічне посилання? Можливо, вам слід додати приклад, щоб продемонструвати свою думку.
Андре Карон

0

Я б зрівняв його з глибиною підмодулю всього однієї і мав сховище, яке б містило всі модулі як підмодулі та нічого іншого, крім README та сценаріїв збірки. Буде окремий сценарій збірки для кожного з пакунків, що пов'язує його залежності. Інакше ви можете мати окремий репо-пакет для пакету.


1
Я не впевнений, чи це було зрозуміло в моєму дописі, але у мене є кілька додатків, які залежать від одних і тих же бібліотек, і я не хочу дублювати сценарії збірки для бібліотек у програмах.
Андре Карон

3
Вам слід детальніше розглянути свою відповідь, щоб продемонструвати, як вона вирішує різні проблеми. Мені не ясно, як саме ви пов'язуєте залежності, враховуючи, що залежно від контексту залежні бібліотеки не знаходяться в одному місці.
Андре Карон

0

Я б не використовував підмодулі.

Це заманливо, так само, як це було у випадку з svn-зовнішніми. Однак чи можете ви бути впевнені, що всі ці проекти, з якими ви пов'язуєтесь, за рік залишаються на одному місці? А як п’ять?

Тому я просто копіюю всі необхідні залежності у свій проект. Це означає, що поки моя репо-дію діє, я можу перевірити точний стан.

В основному у мене така структура папки:

myproject/... [sources etc]
ext/ [third-party dependencies]


e.g. ext/boost, ext/cppunit

Хоча це не дуже приємно з точки зору дискового простору, я ціную гарантію, що зможу перевірити кожен стан, записаний до тих пір, поки РЕПО доступний набагато вище.

Крім того, існує маса проблем з підмодулями, як описано тут


Я впевнений, що вони знаходяться в потрібному місці, тому що я їх підтримую :-) Також будьте уважні щодо копіювання проектів через умови перерозподілу.
Андре Карон

Гаразд, це зменшує проблему. І ліцензування: Так, ви повинні бути обережними, але це зовсім інша проблема.
Вільберт

0

Тут стикаються з точно такою ж проблемою. Одним з рішень може бути мати деякі репо , libsякі будуть тримати core, network, graphяк підмодулі і тільки CMakeLists , що б сказати кожному з LIBS де знайти його залежності. Кожна програма тепер матиме libsяк підмодуль і використовує лише необхідні лібри.

Тестування кожної конфігурації можна налаштувати двома способами:

  • Встановіть core_testing, graph_testing, network_testing як окремі програми
  • Розгорніть перевірені бібліотеки на тестових серверах і знайдіть їх під час виконання тестів за допомогою cmake

Чи не це робить усі лібди доступними для всіх інших?
Андре Карон

За замовчуванням, так. Але це може бути вирішено у cmakelists рівня libs. Якщо вам graphне потрібно знати про це network- не передайте networkпов’язані речі в graphпідрозділ
Макс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.