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

11

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

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

Многие из проблем, с которыми нам приходится сталкиваться в проектах, требуют от нас внесения изменений в несколько библиотек и специфический код проекта. Они часто включают изменения интерфейсов библиотеки, некоторые из которых несовместимы. (Если вам кажется, что это звучит странно: мы взаимодействуем с оборудованием и скрываем определенное оборудование за общими интерфейсами. Почти каждый раз, когда мы интегрируем оборудование другого производителя, мы сталкиваемся со случаями, которые наши текущие интерфейсы не ожидали, и поэтому должны их усовершенствовать.) Например, представьте проект с 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...)

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

Но как мы используем ветвление и тегирование для создания процесса, который позволяет нам реализовывать новые функции в новых проектах без лишних затрат?

SBI
источник
1
Изменение вашего инструментария не должно слишком сильно влиять на ваши процессы. Итак, как вы справились с этой проблемой, прежде чем перейти на git?
Барт ван Инген Шенау
Можно ли просто добавить новый метод в интерфейс, не нарушая существующий, если от него зависит слишком много библиотек? Обычно это не лучшая идея, но, по крайней мере, она позволит вам «продолжить» реализацию новой функции, и вы можете должным образом отказаться от старого метода, когда есть свободное время. Или эти интерфейсы слишком полны для "параллельных интерфейсов"?
Ixrec
1
@Ixrec: мне сказали, что «это не мерзкий способ». Все используют отдельные репозитории для отдельных проектов, поэтому было решено, что мы тоже это делаем.
ВОО
2
Я бы сказал, что это не отдельные проекты, если их часто нужно менять в тандеме. Границы между «проектами» всегда должны иметь какую-то долгосрочную гарантию обратной совместимости imo.
Ixrec
1
@Ixrec: интеграция большего количества аппаратного обеспечения аналогична переносу кода на большее количество платформ: чем больше вы проделали это, тем меньше вам нужно будет переключиться на еще одно оборудование / платформу. Таким образом, в конечном итоге код стабилизируется. Однако сейчас нам нужно найти процесс, который позволит нам оставаться на рынке достаточно долго, чтобы попасть туда.
ВОО

Ответы:

5

Вроде бы выкладываю здесь очевидное, но, возможно, стоит упомянуть об этом.

Как правило, репозитории git разрабатываются для каждой библиотеки / проекта, потому что они, как правило, независимы. Вы обновляете свой проект, а остальное вас не волнует. Другие проекты, зависящие от этого, просто обновят свою библиотеку, когда сочтут нужным.

Однако ваш случай кажется сильно зависимым от коррелированных компонентов, поэтому одна функция обычно влияет на многие из них. И целое должно быть упаковано как связка. Поскольку реализация функции / изменения / ошибки часто требует одновременной адаптации множества различных библиотек / проектов, возможно, имеет смысл поместить их все в один репозиторий.

Есть сильные преимущества / недостатки этого.

Преимущества:

  • Отслеживаемость: ветка показывает все изменения в каждом проекте / библиотеке, связанные с этой функцией / ошибкой.
  • Комплектация: просто выберите тег, и вы получите правильные источники.

Недостатки:

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

Вам решать, стоит ли цена выгоды.

РЕДАКТИРОВАТЬ:

Это будет работать так:

  • Функция X должна быть реализована
  • Создать ветку feature_x
  • Все разработчики работают над этой веткой и работают параллельно над ней, вероятно, в специализированных каталогах, связанных с их проектом / lib
  • Когда все закончится, просмотрите его, протестируйте, упакуйте, что угодно
  • Слейте его обратно в мастер ... и это может быть трудной частью с тех пор, feature_yи feature_zможет быть добавлено тоже. Это становится объединением "кросс-команды". Вот почему это серьезный недостаток.

Просто для справки: я думаю, что в большинстве случаев это плохая идея, и ее следует делать осторожно, потому что недостаток слияния обычно выше, чем тот, который вы получаете при управлении зависимостями / правильном отслеживании функций.

dagnelies
источник
Спасибо, мы действительно сейчас смотрим на это. В свете этого я не понимаю, как мы будем делать ветвления с помощью git. В SVN ветвления означают копирование поддерева (в хранилище) в другое место (в хранилище). Благодаря этому легко создавать ветви любого поддерева в вашем репо, поэтому, если у вас есть много проектов, вы можете разветвлять каждый из них по отдельности. Есть ли что-то подобное в git, или мы всегда сможем разветвить весь репо?
ВОО
@sbi: вы бы разветвляли весь репо. Вы не можете работать с поддеревьями в разных ветвях, что в некотором роде лишило бы смысла в вашем случае. Git не будет ничего «копировать», он просто будет отслеживать изменения в ветке, над которой вы работаете.
dagnelies
Таким образом, это требует, чтобы кто-то создал ветвь функций для одной библиотеки, чтобы также объединить все остальные при объединении или перебазировании. Это настоящий недостаток. (Кстати, SVN также делает только ленивые копии.)
sbi
@sbi: см. редактирование
dagnelies
1
Ну, в настоящее время большинству из нас не комфортно. :-/Более того, даже те, кто (и кто настаивал на переходе на git), не знают, как совместить наш процесс разработки с git. Вздох. Боюсь, это будет несколько трудных месяцев, пока все не станет гладким. Спасибо, в любом случае, ваш самый / единственный полезный ответ до сих пор.
ВОО
4

Решение, которое вы ищете, представляет собой инструмент управления зависимостями в координации с подмодулями git.

Инструменты, такие как:

  • специалист
  • Муравей
  • Композитор

Вы можете использовать эти инструменты для определения зависимостей проекта.

Вы можете требовать, чтобы субмодуль был по крайней мере версии > 2.xx или обозначал диапазон версий, которые совместимы = 2.2. * Или меньше, чем конкретная версия <2.2.3

Всякий раз, когда вы выпускаете новую версию одного из пакетов, вы можете пометить его номером версии, таким образом вы можете вставить эту конкретную версию кода во все другие проекты.

Патрик
источник
Но управление зависимостями - это не наша проблема, это решаемо. В настоящее время мы регулярно вносим изменения во многие библиотеки и должны минимизировать накладные расходы на создание новых версий при сохранении стабильных выпусков проекта. Ваш ответ, кажется, не дает решения для этого.
15:04
@sbi Это поможет справиться с созданием новых версий и поддержанием стабильных выпусков проекта. Поскольку вы можете диктовать, что проект x опирается на проект y версии 2.1.1, вы можете создавать новые версии проекта y, которые не влияют на проект x.
Патрик
Опять же, объявление зависимостей не является нашей проблемой. Мы можем сделать это уже. Проблема заключается в том, как эффективно управлять изменениями в нескольких проектах / библиотеках. Ваш ответ не может объяснить это.
СБИ
@sbi: так в чем именно твоя проблема? Вы вносите изменения, повышаете версию, обновляете зависимости, где это необходимо, и вуаля. То, что вы описали в своем первоначальном посте, типично для Maven & Co. вещи. Каждый дистрибутив основан на четко определенных версионных библиотеках. Как это может быть более понятно?
августа
@arnaud: Сроки выполнения такого процесса (в настоящее время довольно распространенные) изменений, проходящих через три или более слоев, убьют нас. Я думал, что мой вопрос описал это.
суббота,
0

подмодули

Вы должны попробовать git submodules , как предлагается в одном комментарии.

Когда проект 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) вы можете легко увидеть, какие версии библиотек использует каждый проект, и вы можете независимо обновлять их в соответствии с вашими потребностями. Подмодули идеально подходят для вашей ситуации и не замедляют процесс.

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

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

CoreDump
источник
Вы описываете, как решить проблему зависимости (с которой, как я уже говорил, мы уже разобрались), и отрицаете саму проблему, с которой мы столкнулись. Почему ты вообще беспокоишься? (FWIW, мы пишем программное обеспечение, которое управляет электростанциями. Чистый, безопасный и тщательно проверенный код является основной функцией.)
sbi
@sbi Что такое подмодули, если не особый случай ветвления и тегирования? Вы думаете, что подмодули предназначены для управления зависимостями, потому что они также отслеживают зависимости. Но, конечно, пожалуйста, заново изобретайте подмодули с тегами, если хотите, я не против. Я не понимаю вашу проблему: если проверенный код является основной функцией, вы должны выделить время для проверки. Вы не увязли, вы идете как можно быстрее с наложенными на вас ограничениями.
coredump
Отзывы очень важны для нас. Это одна из причин, по которой мы обеспокоены тем, что проблема (и ее обзоры) разделена на несколько обзоров для нескольких изменений в нескольких репозиториях. Кроме того, мы не хотим зацикливаться на том, чтобы управлять нами до смерти из-за одной проблемы: мы бы предпочли потратить время на написание и просмотр кода. Подмодули: пока что я слышал о них только то, что «не беспокойся, это не мерзкий путь». Что ж, учитывая, что наши требования кажутся настолько уникальными, может быть, нам следует пересмотреть это решение ...
sbi
0

Итак, я понимаю, что для P1 вы хотите изменить интерфейс L3, но вы хотите, чтобы другие P2 и P3, которые зависят от интерфейса L3, изменились сразу. Это типичный случай обратной совместимости. Есть хорошая статья об этой сохраняющей обратной совместимости

Есть несколько способов решить эту проблему:

  • Вы должны каждый раз создавать новые интерфейсы, которые могут расширять старые интерфейсы.

ИЛИ ЖЕ

  • Если вы хотите удалить старый интерфейс через некоторое время, у вас может быть несколько версий интерфейсов, и как только все зависимые проекты будут перемещены, вы удалите старые интерфейсы.
Удай Шанкар
источник
1
Нет, обратная совместимость обеспечивается через ветки релизов и не является нашей проблемой. Проблема в том, что мы сидим на быстро изменяющейся в настоящее время базе кода, которая сейчас хочет разделиться на библиотеки, несмотря на то, что интерфейсы все еще находятся в фазе, где они часто меняются. Я знаю, как управлять такими животными в SVN, но не знаю, как это сделать в git, не утонув в администрации.
СБИ
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 будут смотреть на вас странно, если вы это сделаете ...

Сору
источник
msgstr "это считается ошибкой процесса, если вам нужно изменить все 4 вместе" . На самом деле это не так. На самом деле, это именно то, что мы сделали, используя SVN.
СБИ
В таком случае, я думаю, что нет проблем с простым размещением всех проектов в хранилище.
сору
Сейчас мы оцениваем размещение библиотек только в двух репозиториях. Это все же больше, чем один, но гораздо меньше, чем «один на каждый проект», и библиотеки вполне можно разделить на две группы. Спасибо за ваш вклад!
ВОО
PS: «Я полагаю, вы вряд ли хотите переключать языки». Это встроенный материал. :)
ВОО
-1

Существует простое решение: разрезать ветки релизов по всему репозиторию, объединять все исправления со всеми активно поставляемыми релизами (это легко сделать в ясном случае в git).

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

zzz777
источник
Не могли бы вы уточнить? Я не уверен, что вы предлагаете.
sbi
В ясном случае вы определяете точку ветвления как базовую ветвь и метку времени. У вас есть следующая иерархия: базовая ветка -> release-development-branch -> private-development branch. Все разработки выполняются в частных филиалах, а затем объединяются по иерархии. Ветви релизов клиентов разорваны веткой релиз-разработка. Я не очень хорошо знаком с git, но, похоже, ближе всего разобраться в бесплатных системах контроля версий.
zzz777
Внимательное прочтение моего вопроса должно было показать вам, что у нас есть проблемы с накладными расходами, связанными с распространением изменений между репозиториями. Это не имеет ничего общего с вашим ответом.
15:04
@sbi Извините, я неправильно понял ваш вопрос. И я боюсь, что рано или поздно вы столкнетесь с ужасным беспорядком.
zzz777