Як робити версії для десятка бібліотек у git, паралельно працювали


11

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

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

Багато питань, з якими нам доводиться вирішувати проекти, вимагають зміни в декількох бібліотеках та конкретного коду проекту. Вони часто включають зміни інтерфейсів бібліотеки, деякі з яких несумісні. (Якщо ви думаєте, що це звучить риба. Ми взаємодіємо з обладнанням і ховаємо конкретне обладнання за загальними інтерфейсами. Майже кожен раз, коли ми інтегруємо якесь інше обладнання виробника, ми стикаємося з випадками, коли наші поточні інтерфейси не передбачали, і тому доводиться їх удосконалювати.) наприклад, уявіть проект з P1використанням бібліотек L1, L2і L3. L1також використовує L2і L3, і також L2використовує L3. Графік залежності виглядає приблизно так:

   <-------L1<--+
P1 <----+  ^    |
   <-+  |  |    |
     |  +--L2   |
     |     ^    |
     |     |    |
     +-----L3---+

Тепер уявімо, що функція цього проекту вимагає змін P1та L3зміни інтерфейсу L3. Тепер додайте проекти P2та P3в суміш, які також посилаються на ці бібліотеки. Ми не можемо дозволити собі переключити їх на новий інтерфейс, виконати всі тести та розгорнути нове програмне забезпечення. То яка альтернатива?

  1. впровадити новий інтерфейс у L3
  2. зробіть запит на тягу L3та чекайте на перегляд
  3. злиття змін
  4. створити новий випуск L3
  5. почніть працювати над функцією P1, зробивши її посиланням на L3новий випуск, а потім реалізуйте функцію у P1відділенні функції
  6. зробіть запит на потяг, перегляньте це та об’єднайте

(Я щойно помітив, що забув переключитися L1і L2до нового випуску. І навіть не знаю, куди це вставити, бо це потрібно робити паралельно з P1...)

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

Але як ми використовуємо розгалуження та тегування для того, щоб створити процес, який дозволяє нам реалізовувати нові функції в нових проектах без надто великих витрат?


1
Зміна інструментарію не повинна занадто сильно впливати на ваші процеси. Отже, як ви вирішили цю проблему перед тим, як перейти на git?
Барт ван Іґен Шенау

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

1
@Ixrec: Мені сказали, що "це не суть способу" робити речі. Усі використовують індивідуальні сховища для окремих проектів, тому було вирішено і ми.
sbi

2
Я зауважу, що вони не є окремими проектами, якщо їх часто доводиться змінювати в тандемі. Межі між "проектами" завжди повинні мати якусь довгострокову гарантію сумісності назад.
Іксрек

1
@Ixrec: Інтеграція більшої кількості апаратних засобів схожа на перенесення коду на більше платформ: чим більше ви це зробили, тим менше потрібно змінити на ще одне обладнання / платформу. Тож у перспективі код стабілізується. Однак зараз нам потрібно буде знайти процес, який дозволяє нам залишатися на ринку досить довго, щоб потрапити туди.
sbi

Відповіді:


5

Вигляд викладу очевидного тут, але, можливо, варто згадати про це.

Зазвичай git repos розроблені відповідно до ліб / проекту, оскільки вони, як правило, незалежні. Ви оновлюєте свій проект і не піклуєтесь про інше. Інші проекти залежно від цього просто оновлюватимуть свою область, коли вони вважають за потрібне.

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

У цьому є сильні переваги / недоліки.

Переваги:

  • Простежуваність: філія показує все, що було змінено у кожному проекті / лібі, пов'язаному з цією функцією / помилкою.
  • Пакет: просто виберіть тег, і ви отримаєте всі джерела.

Недоліки:

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

Вам належить знати, чи варта ціна вигоди.

Редагувати:

Це діятиме так:

  • Функція X повинна бути реалізована
  • Створити відділення feature_x
  • Усі задіяні розробники працюють над цією галуззю і паралельно працюють над нею, ймовірно, у спеціалізованих довідниках, пов’язаних з їх проектом / lib
  • Після того, як він закінчиться, перегляньте його, протестуйте, упакуйте, що завгодно
  • Об'єднати його назад в майстра ... і це може бути жорсткою частиною , так як в той же час feature_yі , feature_zможливо, був доданий також. Це стає злиттям "перехресної команди". Ось чому це серйозний недолік.

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


Дякую, ми справді на це дивимось. Що я не розумію у світлі цього, це те, як ми робимо розгалуження з git. У SVN розгалуження означає копіювання піддерева (у сховище) кудись ще (у сховище). З цим легко створити гілки будь-якого піддіреця у своєму репо, тому якщо у вас є багато проектів, ви можете відгалужувати кожне з них окремо. Чи є щось подібне в git, чи ми завжди зможемо лише розгалужити ціле репо?
sbi

@sbi: ти би розгалужував цілий репо. Ви не можете працювати з підкреслими в різних галузях, що може би перемогти точку у вашому випадку. Git нічого не "копіює", він просто відстежує зміни у галузі, над якою ви працюєте.
dagnelies

Отже, це вимагає, щоб хтось створив гілку функцій для однієї бібліотеки, щоб також об'єднати всі інші при об'єднанні чи повторному виданні. Це справжній недолік. (BTW, SVN також тільки коли-небудь робить ліниві копії.)
sbi

@sbi: див. редагувати
dagnelies

1
Ну, в даний час більшості з нас не комфортно. :-/Більше того, навіть ті, хто є (і хто наштовхнувся на рух до git), не знають, як зробити наш процес розробки відповідним git. Зітхнути. Боюсь, пройде кілька важких місяців, поки все не почне гладшати. У будь-якому випадку, дякую, ваша - це найпопулярніша відповідь поки що.
sbi

4

Ви шукаєте рішення - це інструмент управління залежністю в координації з підмодулями git

Такі інструменти, як:

  • Мейвен
  • Мураха
  • Композитор

Ці інструменти можна використовувати для визначення залежностей проекту.

Ви можете вимагати від підмодулю мати принаймні версію > 2.xx або позначати діапазон версій, сумісних = 2.2. * Або менше, ніж певна версія <2.2.3

Щоразу, коли ви випускаєте нову версію одного з пакетів, ви можете позначити її номером версії, таким чином ви можете ввести цю конкретну версію коду у всі інші проекти


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

@sbi Це допоможе керувати витратами на створення нових версій та підтримання стабільних релізів проектів. Оскільки ви можете продиктувати, що проект x покладається на проект y версія 2.1.1, ви можете створити нові версії проекту y, які не впливали б на проект x.
Патрік

Знову ж таки, декларування залежностей не є нашою проблемою. Ми вже можемо це зробити. Проблема полягає в тому, як ефективно керувати змінами в кількох проектах / бібліотеках. Ваша відповідь не пояснює цього.
sbi

@sbi: так у чому саме полягає ваша проблема? Ви вносите зміни, нарікаєте версію, оновлюєте залежності, де це потрібно, і вуаля. Те, що ви описали у своєму початковому дописі, - це типовий maven & co. речі. Кожен розподіл базується на чітко визначених версіях. Як це могло бути зрозуміліше?
dagnelies

@arnaud: Час повороту такого процесу для (в даний час досить поширених) змін, прорізаючи три або більше шарів, нас би вбили. Я думав, моє запитання так описало.
sbi

0

Підмодулі

Спробуйте спробувати підмодулі , як це запропоновано в одному коментарі.

Коли проект P1відноситься до трьох подмодулей L1, L2і L3, на самому ділі зберігає посилання на конкретні фіксацій у всіх трьох сховищах: це ті робочі версії кожної бібліотеки для цього проекту .

Таким чином, кілька проектів можуть працювати з декількома підмодулями: вони P1можуть посилатися на стару версію бібліотеки, L1тоді як проект P2використовував нову версію.

Що станеться при доставці нової версії L3?

  • впровадити новий інтерфейс у L3
  • здійснити, протестувати , зробити запит на перетягування, переглянути, об'єднати, ... (цього не можна уникнути)
  • забезпечити L2роботи L3, виконувати, ...
  • забезпечити L1роботи з новими L2, ...
  • забезпечити P1роботу з новими версіями всіх бібліотек:
    • всередині P1«s локальної робочої копії L1, L2і L3, fetche зміни ви зацікавлені.
    • вносити зміни, git add L1 L2 L3здійснювати нове посилання на модулі
    • тягнути запит на P1, перевірити, переглянути, потягнути запит, об'єднати ...

Методика

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

Так, для цього потрібні незалежні огляди, оскільки ви змінюєте:

  • бібліотека
  • бібліотеки, які від цього залежать
  • проекти, які залежать від декількох бібліотек

Чи не будете ви відкладені без роботи, бо доставляєте лайно? (Можливо, насправді). Якщо так, то вам потрібно виконати тести та переглянути зміни.

За допомогою відповідних інструментів git (навіть gitk) ви можете легко побачити, які версії бібліотек використовує кожен проект, і ви можете оновити їх незалежно відповідно до ваших потреб. Підмодулі ідеально підходять для вашої ситуації і не уповільнюють ваш процес.

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

(Редагувати) Ще одна річ, яка може вам допомогти - це групувати відповідні огляди коду. Ви здійснюєте всі зміни і чекаєте, поки ви поширите ці зміни до всіх бібліотек і проектів, які використовують їх, перш ніж надсилати запити на виклик (або перед тим, як піклуватися про них). Ви в кінцевому підсумку робите більший огляд для всього ланцюга залежностей. Можливо, це допоможе вам заощадити час, якщо кожна локальна зміна невелика.


Ви описуєте, як вирішити проблему залежності (яку, як я вже говорив раніше, ми розібрали) і заперечуєте ту саму проблему, яку ми маємо. Чому ви навіть турбуєтесь? (FWIW, ми пишемо програмне забезпечення, яке приводить в дію електростанції. Чистий, безпечний і ретельно переглянений код є головною особливістю.)
sbi

@sbi Що таке підмодулі, якщо не окремий випадок розгалуження та тегування? Ви вважаєте, що субмодулі стосуються управління залежністю, оскільки вони також відстежують залежності. Але обов'язково, будь ласка, винаходити підмодулі з тегами, якщо хочете, я не проти. Я не розумію вашої проблеми: якщо переглянутий код є головною функцією, ви повинні витратити трохи часу на огляди. Вас не забили, ви йдете якнайшвидше з обмеженнями, накладеними на вас.
coredump

Відгуки для нас дуже важливі. Це одна з причин, коли ми стурбовані тим, що питання (і його огляди) розбито на кілька оглядів для кількох змін у кількох сховищах. Плюс до того, що ми не хочемо зациклюватися на управлінні нами смертю через одну проблему, це те, що ми краще витратим час на написання та перегляд коду. Знову підмодулі: поки що єдине, що я чув про них, - це "не турбуйся, це не суть". Ну, враховуючи, що наші вимоги здаються настільки унікальними, можливо, ми повинні переглянути це рішення ...
sbi

0

Тож, що я розумію, це ти для P1, ти хочеш змінити інтерфейс L3, але ти хочеш, щоб інші P2 і P3, які залежать від інтерфейсу L3, змінилися відразу. Це типовий випадок зворотної сумісності. Є приємна стаття про цю збереження відсталої сумісності

Є кілька способів вирішити це:

  • Вам потрібно створювати нові інтерфейси щоразу, які можуть розширювати старі інтерфейси.

АБО

  • Якщо ви хочете звільнити старий інтерфейс через деякий час, ви можете мати декілька версій інтерфейсів, і коли всі залежні проекти перемістяться, ви видалите старі інтерфейси.

1
Ні, зворотна сумісність забезпечується через гілки випуску, і це не наша проблема. Проблема полягає в тому, що ми сидимо на швидко змінюється базі даних коду, яку зараз хочуть розділити на бібліотеки, незважаючи на те, що інтерфейси все ще знаходяться у фазі, де вони часто змінюються. Я знаю, як керувати такими звірами в SVN, але не знаю, як це зробити в git, не будучи утопленим в адміністрації.
sbi

0

Якщо я зрозумію вашу проблему:

  • у вас є 4 взаємопов'язані модулі, P1 і L1 до L3
  • вам потрібно внести зміни до P1, що в кінцевому підсумку вплине на L1 на L3
  • це вважається збоєм процесу, якщо вам доведеться змінити всі 4 разом
  • це вважається збоєм процесу, якщо вам доведеться змінити їх усі 1 на 1.
  • це вважається збоєм у процесі, якщо вам доведеться заздалегідь визначити шматки, в яких потрібно внести зміни.

Отже, мета полягає в тому, що ви можете зробити P1 і L1 за один раз, а потім через місяць L2 і L3 в інший.

У світі Java це тривіальний і, можливо, спосіб роботи за замовчуванням:

  • все відбувається в одному сховищі без відповідного використання розгалуження
  • модулі компілюються + зв'язані разом maven на основі номерів версій, не факт, що всі знаходяться в одному дереві каталогів.

Таким чином, ви можете мати на локальному диску код для L3, який не збирався б, якщо він компілювався проти копії P1 в іншому каталозі на вашому диску; на щастя, це не так. Java може це зробити прямо, тому що для компіляції / зв’язування казок розміщується проти компільованих файлів jar, а не вихідного коду.

Мені не відомо, що раніше існувало широко використовуване рішення цієї проблеми для світу C / C ++, і я б уявив, що ти навряд чи хочеш переключити мови. Але щось легко можна зламати разом із файлами make, які роблять рівнозначну річ:

  • встановлені бібліотеки + заголовки до відомих каталогів із вбудованими номерами версій
  • змінили контури компілятора на модуль до каталогу для відповідних номерів версій

Ви навіть можете використовувати підтримку C / C ++ у Maven , хоча більшість розробників C дивляться на вас дивно, якби ви ...


"це вважається збоєм процесу, якщо вам доведеться змінити всі 4 разом" . Насправді це не було б. Насправді це саме те, що ми зробили за допомогою SVN.
sbi

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

Зараз ми оцінюємо розміщення бібліотек лише у двох сховищах. Це все-таки більше одного, але набагато менше, ніж «по одному на кожен проект», і бібліотеки дуже добре можна розділити на дві групи. Дякуємо за ваш внесок!
sbi

PS: "Я думаю, ви навряд чи хочете переключити мови". Це вбудовані речі. :)
sbi

-1

Є просте рішення: вирізати гілки випуску по всьому сховищу, об'єднати всі виправлення з усіма активно відправленими випусками (це легко в явному випадку має бути можливим у git).

Усі альтернативи створять жахливий безлад з часом та з ростом проекту.


Чи можете ви, будь ласка, докладно? Я не впевнений, що ти пропонуєш.
sbi

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

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

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