Как структурировать репозиторий, состоящий из нескольких библиотек и приложений

Я выиграл задачу реструктуризации / воссоздания существующего репозитория кода, используя 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-адресом.