SVN и код совместно используются несколькими проектами

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

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

Приведу пару сценариев и связанных с ними проблем.

а) Поместите общий код в отдельный транк (или репозиторий) и используйте svn: external.

В случае, если мы разветвим какой-то из проектов, возникнут две проблемы:

  • Любая модификация общего кода, сделанная в стволе, будет распространена на ветку, потому что svn: external примет изменения.
  • В случае, если нам понадобится в какой-то момент вернуться и собрать именно тот код, который был собран для выпуска, нам будет сложно получить точный код, потому что snv: external снова будет брать последнюю копию общего кода вместо код в тот момент, когда проект был запущен.

Насколько я понимаю, есть одна работа. Как только мы ответим, мы можем изменить svn: external, чтобы получить точную версию общего кода. Однако здесь снова две ловушки:

  • Не забывайте делать это каждый раз при ветвлении. (Ненавижу такие вещи, о которых легко забыть).
  • Вы не можете изменить общий код, если вам нужно сделать исправление для разветвленного / выпущенного проекта.

б) Другое решение - разветвить общий код, когда проект разветвляется, и изменить внешний, чтобы он указывал на связанную копию общего кода.

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

Я что-нибудь упускаю? Есть ли какой-нибудь разумный способ справиться с этим?


person Victor Ronin    schedule 28.10.2009    source источник
comment
Вы нашли какое-нибудь решение для этого?   -  person dhiraj suvarna    schedule 28.02.2017


Ответы (6)


Лично я веду отдельный репозиторий, а затем использую [http://svnbook.red-bean.com/en/1.0/ch07s03.html svn: externals] атрибут.

SVN Externals позволяет вам связываться с другими репозиториями (даже с теми, которые вы не запускаете, например репозиторий smarty subversion), когда вы запускаете svn update, как ваш проект, так и внешнее репо будут обновлены.

с внешними элементами SVN вы также можете ссылаться на определенные версии, используя что-то вроде http://path-to-project.com/svn/thing -r1234 для выпусков и других вещей, которые вам нужно сохранить статичными.

Лучшая практика, IMHO, - всегда указывать ревизию, а затем обновлять номер ревизии при внесении изменений в общую библиотеку, чтобы вы могли отслеживать, ПОЧЕМУ вы обновили эти данные. также сохраняет все в здравом уме, когда вы помечаете или разветвляете основной проект.

person Mike Valstar    schedule 28.10.2009
comment
+1 для напоминания о конкретной ревизии внешнего вида - person Michael Hackner; 28.10.2009
comment
Это действительно хорошая практика! Или, когда это возможно, указывайте теги другого репозитория в svn: external links (что должно гарантировать неизменяемость и легче интерпретировать с точки зрения используемой версии). - person RedGlyph; 28.10.2009

У вас два правильных ответа с двумя наборами недостатков.
Вот что я бы порекомендовал

Поместите ваш общий код в другой репозиторий, пометьте код версией выпуска. Создайте svn externals в вашем каталоге магистрали, который указывает на ваш тег.

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

В качестве альтернативы попробуйте создать отдельный выпуск вашей библиотеки и ссылаться на библиотеку как на jar или lib / so.

person Michael Brunton-Spall    schedule 28.10.2009

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

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

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

Недостаток, который мы видим до сих пор в этом безумном методе ^ W, заключается в том, что последующие проекты, находящиеся в очень разработке (скажем, на ранних этапах создания новой библиотеки), требуют того, что может показаться чрезмерным количеством обновления для восходящего проекта. Тестирование восходящего проекта может потребовать обновления общей библиотеки, компиляции, копирования этого двоичного восходящего потока и компиляции / развертывания / любого другого восходящего проекта. Однако, как только начальное безумие разработки библиотеки замедлится и библиотека станет в некоторой степени стабильной, эта «проблема» исчезнет.

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

person supermagic    schedule 28.10.2009
comment
Это именно то, что мы планируем сейчас, с теми же обоснованиями. - person Jim T; 29.10.2009
comment
Я согласен с подходом supermagic. Подумайте об общих библиотеках, а не об общих кодовых файлах / проектах. Добавьте скомпилированный двоичный файл для общей библиотеки в свой проект. Этот подход имеет тот же эффект, что и включение внешних элементов в тег, но без проблем с обслуживанием из-за управления внешними элементами. Некоторые проблемы, с которыми я столкнулся, связаны с созданием тега с внешними элементами ствола, ствола и ветви, указывающими на один и тот же внешний вид. На мой взгляд, риски внешних факторов перевешивают их преимущества. - person mcdon; 03.09.2010
comment
Это отлично работает, если вам нужны только двоичные файлы, но если вы столкнетесь с ошибкой в ​​будущем в одной из общих библиотек, вы застрянете в поисках версии библиотеки, которая была включена в тег или ветку. - person 3Dave; 22.09.2010

Мы используем такую ​​структуру единого репозитория:

/trunk/project1
/trunk/classlibrary (shared code)
/trunk/project2

В C # (который может быть другим языком) project1 и project2 включают ссылку на classlibrary. Когда мы строим (вот большое преимущество скомпилированной модели .NET), обнаруживаются любые несоответствия между собираемым проектом и class_library. Эти несоответствия устраняются до фиксации изменений. Используя серверный инструмент сборки (мы используем CruiseControl.NET), мы можем построить все проекты одновременно, что сообщит нам о любых проблемах.

Если ваш project1 и project2 не должны ссылаться на конкретную версию classlibrary (чего мы избегаем, пытаясь заставить project1 и project2 всегда использовать последнюю версию class_library), это работает невероятно гладко.

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

person 3Dave    schedule 28.10.2009
comment
Мне очень не нравится эта структура. Все смешано и становится слишком сложным. Изменения в библиотеке классов немедленно принимаются обоими проектами, что означает, что она становится хрупкой и неприкасаемой в масштабе. У вас нет возможности управлять своей библиотекой как собственной сущностью. По сути, если вы выпускаете project1 и project2 как отдельные продукты, то этот макет вызывает много проблем. - person Jim T; 29.10.2009
comment
Думаю, здесь есть разные точки зрения. Я предпочитаю это, потому что это не позволяет нам иметь несколько версий библиотеки классов, которые могут привести к несовместимости или несогласованности между приложениями, если интерфейс к классу в библиотеке изменен. Кроме того, это будет зависеть от того, что вы имеете в виду в этой области. В этом примере два проекта - это административный сайт и общедоступный сайт одного и того же проекта - это отдельные проекты веб-приложений, но по уважительной причине они очень тесно связаны. - person 3Dave; 29.10.2009

Моя рекомендация по работе с общим кодом (особенно с Java и .NET или библиотекой C / C ++) - использовать два набора репозиториев: один для исходного кода, а другой для управления версиями выпущенных образов. Когда вы вносите изменения в «общий» проект, вы фиксируете исходные изменения в исходном дереве, затем строите его, а затем публикуете двоичные файлы, фиксируя их как новую ревизию в дереве выпуска. Проекты, использующие «общий» проект, затем используют свойство svn: externals для добавления выпущенных двоичных файлов. Нет соблазна изменить локальные образы общего кода. Если кто-то хочет изменить «общий» код, он делает это с помощью обычных методов разработки для этого проекта.

Для получения дополнительных сведений см. ответьте на аналогичный вопрос.

person Craig Trader    schedule 28.10.2009
comment
Это несколько неправильное использование инструмента управления версиями, что мы склонны осуждать в нашей команде, но что, я признаю, удобно. Предпочтительно хранить двоичные файлы в общей структуре каталогов (которая включает версию), если есть возможность воссоздать их из источников с поддержкой версий (если требуется отладка и т. Д.). Основная проблема с хранением двоичных файлов в репозитории заключалась в ненужной доплате за сервер. - person RedGlyph; 28.10.2009
comment
Я тоже сохраняю версии источников (конечно). Использование репозитория предпочтительнее общей файловой системы, когда вы работаете с распределенной командой разработчиков - все, что вам нужно предоставить, это доступ для подрывной деятельности (через http / https) вместо того, чтобы делать CIFS через VPN. - person Craig Trader; 29.10.2009

Ответ, которого не хватает в вашем списке:

c) Всегда указывайте внешние элементы на конкретную версию общего кода.

Это работает замечательно:

  1. Вы всегда можете загрузить определенную версию своего проекта и гарантировать сборку.
  2. Ветвление и тегирование - это операция только на пути проекта.
  3. Обновления общего кода могут быть сделаны для 1 проекта, но второй проект не получит их, пока не будет готов.
  4. Когда второй проект действительно принимает изменения, вы получаете событие, записанное в вашем стволе, в котором говорится, что оно было принято и почему.
  5. Вы получаете возможность выпустить определенную версию библиотеки с конкретными функциями для проекта. Это может помочь вам выбраться из дыры, если проект не готов к изменению API, но требует исправления ошибок и т. Д.

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

person Jim T    schedule 29.10.2009