Общий код SVN с внешними элементами

#svn #version-control

#svn #управление версиями

Вопрос:

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

 -trunk-Project1
      -Project2
      -Shared
  

Оба проекта 1 и 2 имеют внешний для включения общего кода. Внешнее указывает на конкретную ревизию, чтобы не прерывать сборку project2 во время работы над project1 и общим кодом. Из-за этого возникает проблема.

Когда вносятся изменения в общий код и я выполняю фиксацию (с помощью tortoise SVN), изменения сохраняются как для project1, так и для общего кода и автоматически передаются в SVN в виде одной ревизии. Однако, когда я или коллега выполняем обновление, проект не будет собран, потому что внешний svn указывает на «старую» ревизию.

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

Ответ №1:

Я думаю, у вас есть несколько вариантов. Первое — использовать единый модуль с ветвями, как предлагает Мартин. У вас будет ветвь для каждого активного проекта или для потока разработки. Изменения в общем коде будут обнаружены при обратном объединении с магистралью.

например

 Module
    |
      trunk
    |     Project1
    |     Project2
    |     Shared
    |
      branches
        |
          Project1Development
        |      Project1 [active development here]
        |      Project2 
        |      Shared [active development here]
        |
          Project2Development
               Project1 
               Project2 [active development here]
               Shared [active development here] 
  

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

 Project1
    |
      trunk [svn:external to a branch of Shared]

Project2
    |
      trunk [svn:external to a branch of Shared]

Shared
    |
      trunk
    |
      branches
        |
          Project1Development
        |
          Project2Development
  

Каждый проект будет использовать свой собственный вид магистрали. Опасность здесь в том, что ветви становятся слишком длинными — вам нужно будет дисциплинированно объединять их и удалять, возможно, после каждого выпуска. Ветви Shared следует создавать только тогда, когда требуются изменения shared для конкретного проекта.

В-третьих, вы продолжаете использовать внешние элементы, как и сейчас, и испытываете трудности с закреплением версий. Я бы изменил ваш репозиторий, чтобы он был похож на второй рисунок выше, если вы делаете это — то, что у вас есть с внешними элементами внутри проекта, немного попахивает.

Комментарии:

1. Второе предложение в основном заключается в замене номера редакции на ветвь, обеспечивающую дополнительную гибкость. Как указывалось, требуется больше администрирования для поддержания актуальности, но я начинаю верить, что это неотъемлемо от совместного использования кода. Хотя с реальной отдельной библиотекой у вас возникают во многом те же проблемы, но они распределены по двум репозиториям. Внешний используется только для предотвращения дополнительной работы в нашем процессе сборки.

Ответ №2:

Вы должны использовать svn: external, когда у вас более одного репозитория и вам нужно смешать исходные коды из всех репозиториев для сборки вашего проекта. Основываясь на вашем вопросе, я бы сказал, что у вас есть только 1 репозиторий, следовательно, нет необходимости в svn: external.

Вы могли бы использовать ветви. Оба проекта Project1 и project2 вносят изменения в общий доступ в своей собственной ветке. Вам пришлось бы заключить хорошие рабочие соглашения, чтобы как можно чаще интегрировать изменения в ветвях в магистраль (меньшие различия легче объединять) и убедиться, что сборка в магистрали никогда не прерывается.

Я могу порекомендовать статью Хенрика Книберга о контроле версий, она прекрасно освещает эту тему.

Комментарии:

1. Я прочитал статью, спасибо, что указали на это. В нем прекрасно описаны стратегии ветвления для выпусков и одновременной разработки. Однако я не вижу, чтобы в нем упоминалось несколько проектов и общий код между ними, или я что-то упускаю.

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

Ответ №3:

Ваша проблема в том, что Project1 и Project 2 требуют определенных версий Shared. Поэтому вам нужно сделать это явным в вашем макете.

Например, вы могли бы сделать это:

-магистральный — Проект 1 — Project1Share — Проект 2 — Project2Share — Общий

И имейте Project1Share и Project2Share в качестве версионных внешних элементов, указывающих на конкретные ревизии Shared, а «Shared» — это последняя редакция кода этой разделяемой библиотеки.

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

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

Если правило таково, что Project1 всегда выполняется с использованием последней версии shared, а project2 — с использованием определенных версий, то project1shared external может быть неверсированным, а project2 — с одной версией.

Ответ №4:

Пока все хорошие ответы — но есть другой вариант: использовать теги. По завершении разработки требуется повторно связать внешние элементы с P1 и P2, которые указывают на новый общий проект. До тех пор вы хотите, чтобы P1 и P2 указывали на старую, заведомо рабочую версию Shared.

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

Если вы выпускаете P1 и P2 в разное время, вы все равно можете использовать этот подход — когда вы помещаете проект в ветку tags, вы устанавливаете для его внешних элементов текущую версию общего проекта. Когда следующий проект будет помечен (и общий проект будет обновлен), старый проект по-прежнему будет указывать на правильную версию Shared, пока не будет помечен его следующий выпуск и так далее.