Как структурировать репозиторий, состоящий из нескольких библиотек и приложений
Я выиграл задачу реструктуризации / воссоздания существующего репозитория кода, используя Git или Subversion. История репозитория не обязательно важна в этом частном случае. Проанализировав ситуацию, я обнаружил некоторые проблемы с определением хорошего макета. Я прочитал много блогов и тем, но я все еще не уверен, что является лучшим макетом.
существующий репозиторий содержит набор файлов include, набор библиотек, которые частично зависят от друг друга, и многие из них зависят от набора include файлов. Кроме того, существует два проекта приложений, которые зависят от набора библиотек. Кроме того, существует набор скриптов, который использует одно из приложений и некоторые дополнительные сведения о конфигурации. Я нарисовал график, чтобы прояснить ситуацию:
+---------->include files
| ^
| |
library A -----> library B <----- library C <----- library D
^ ^ | ^
| | | |
| +--------------------------------+ |
| |
application 1 application 2 --------------------+
^
|
script -----> configuration information
цель иметь план где каждый компонент можно начать как можно независимо, и иметь отпуск (для внешних клиентов) это содержит набор всех компонентов в определенных версиях тегов, чтобы можно было вернуться назад во времени и создать программное обеспечение для определенного выпуска.
Я придумал следующую структуру:
trunk/
include/
lib/
library A/
library B/
library C/
library D/
app/
application 1/
application 2/
tags/
1.0/
include/
lib/
library A/
library B/
library C/
library D/
app/
application 1/
application 2/
1.1/
include/
lib/
library A/
library B/
library C/
library D/
app/
application 1/
application 2/
...
каждый раз, когда я создаю новую версию, я просто копирую весь репозиторий в новый подкаталог в тегах.
проблема с этим решением заключается в том, что библиотеки не имеют отдельных каталогов тегов для себя, и что я только хочу иметь выпуск, состоящий из помеченных компонентов, и это решение не отображает, какие компоненты имеют версии тегов в выпуске. Я рассмотрел возможность использования отдельных репозиториев, а затем создать главный репозиторий, который имеет подкаталог releases, где я связываю все необходимые компоненты с подкаталогом "svn:externals" и определенным подкаталогом тегов, но разные библиотеки и включенные файлы зависят друг от друга, и я не вижу, как разбить код на отдельные сущности.
любой идеи?
=============== вопрос продолжался 28-1-2011 ===============
хорошо, я нарисовал график того, как я планирую новый макет. Цель состоит в том, чтобы связать теги различных зависимостей с помощью метода svn: externals в пределах одного репозиторий, например, я бы установил svn: externals в багажник/проекты/Либ/library2/зависимостей ^/теги/проекты/включить/СТД/1.3.
trunk/
projects/
include/
std/
lib/
library1/
dependencies/
std/ --> tags/projects/include/std/1.2
library2/
dependencies/
std/ --> tags/projects/include/std/1.2
library1/ --> tags/projects/lib/library1/1.4.3
library3/
dependencies/
std/ --> tags/projects/include/std/1.3
library1/ --> tags/projects/lib/library1/1.4
app/
application1/
dependencies/
library3/ --> tags/projects/lib/library3/1.1
application2/
dependencies/
library1/ --> tags/projects/lib/library1/2.1
application3/
dependencies/
std/ --> tags/projects/include/std/1.2
library2/ --> tags/projects/lib/library2/1.5.2
config/
configuration1/
dependencies/
application1/ --> tags/projects/app/application1/2.3
configuration2/
dependencies/
application1/ --> tags/projects/app/application1/1.6
configuration2/
dependencies/
application2/ --> tags/projects/app/application1/1.6
tags/
projects/
include/
std/
1.2/
1.3/
lib/
library1/
1.4.3/
1.4/
2.1/
library2/
1.5.2/
library3/
1.1/
app/
application1/
1.6/
2.3/
branches/
...
оставшиеся вопросы:
- эта конструкция выполнима, или вы видите какие-то существенные недостатки?
- что произойдет, если я скопирую библиотеку в каталог тегов? Это скопирует svn: свойство externals также. Вызовет ли это проблемы или такое поведение желательно?
- я мог бы указать явную ревизию для всех внешних, но тег не должен меняться в любом случае, так что каталог не будет достаточным?
- будет ли репозиторий разделен на репозиторий разработки и репозиторий, использующий svn:external, лучшим решением? См. ответ "Варианты использования" в вопросе каковы преимущества "svn: externals"?.
2 ответов
Я предлагаю вывернуть таксономию наизнанку. В subversion я предлагаю такую таксономию:
companyname/
include/
trunk/
tags/
branches/
libraryA/
trunk/
tags/
branches/
libraryB/
trunk/
tags/
branches/
libraryC
trunk/
tags/
branches/
libraryD/
trunk/
tags/
branches/
application1
trunk/
tags/
branches/
application2
trunk/
tags/
branches/
в git я предлагаю вам создать отдельное репозиторий git для include, libraryA, libraryB, application1 и т. д...
эта структура позволит вам создавать любые зависимости между различными частями (например, ветвь в application1 может зависеть от нестабильной версии проекта libraryA, в то время как головка в application1 может зависеть от стабильная версия проекта libraryA).
эта структура также хорошо работает с большинством инструментов сборки, таких как maven, rake, buildr, ant и т. д.
представленная вами таксономия выглядит как хорошая структура для развернутой версии вашего приложения, но не хорошая структура для управления версиями. Из опыта я думаю, что вам будет лучше, если вы используете структуру, подобную той, которую я предложил для управления версиями, а затем используете скрипт сборки (или инструмент сборки) для создания структура, которую вы указали, когда придет время упаковать/развернуть / отправить приложение.
UPDATE: подробнее о том, как может идти рабочий цикл:
Итак, например, предположим, что мы закончили реализацию исправлений ошибок для Application1 (назовем эту версию 1.0.0). Последние и самые большие изменения в приложение1/багажник. Эта версия Application1 зависит от libraryD v0.5.0. Вы обновляете application1 / trunk / README.txt с примечанием, что эта версия зависит от libraryD версия v0.5.0. Возможно, что более важно, скрипт сборки внутри приложения / trunk знает, как проверить libraryD/tags/0.5.0. Затем создайте тег (который является просто копией транка в текущем состоянии) в application1/tags/1.0.0.
теперь, скажем, проходит неделя, и другой разработчик обновляет libraryD до версии 1.3.0. Вам нужно увеличить application1. Итак, внесите изменения в application1 / trunk. Затем обновите application1 / trunk / README.txt сказать, что теперь вы зависите от libraryD v1.3.0 (и, аналогично, новый скрипт сборки для application1 v1.3.0 будет проверять libraryD / tags / 1.3.0). Скопируйте application1 / trunk в application1/tags / 1.1.0.
теперь вы всегда можете вернуться к application1/tags/1.0.0, если это необходимо (и будьте уверены, что он вытащит код из libraryD/tags / 0.5.0. приложение / tags / 1.1.0 будет использовать libraryD версии 1.3.0.
в subversion и git тег является ссылкой на набор файлов в данный момент времени. Это означает, что теги не занимают много места, поэтому я говорю tag рано и часто ; -)
важный вопрос заключается в том, все ли библиотеки и приложения тесно связаны в один продукт или могут жить независимо друг от друга. IMO помещает их в один репозиторий git только имеет смысл, если все библиотеки и приложения являются одним продуктом, так как кроме svn вы не можете проверить только часть дерева git. Когда библиотеки и приложения независимы, вы можете создать РЕПО для каждого lib/app и склеить их вместе с помощью подмодулей.
подмодули Git похожи к SVN extarnals, но они всегда ссылаются на конкретную ревизию цели, а не только на простой url. Поэтому, когда вы бежите git checkout deadbeef
, вы всегда получаете состояние подмодуля с момента создания commit deadbeef, независимо от того, какой из них является главой ссылочного РЕПО. Таким образом, тег git также принимает состояние каждого подмодуля, в отличие от svn с не закрепленным URL-адресом.