Как вы организуете свой репозиторий контроля версий?

108

Во-первых, я знаю об этом: как бы вы организовали репозиторий Subversion для собственных программных проектов? Далее, собственно вопрос: моя команда реструктурирует наш репозиторий, и я ищу подсказки, как его организовать. (В данном случае SVN). Вот что мы придумали. У нас есть один репозиторий, несколько проектов и несколько перекрестных ссылок svn: externals

\commonTools /*tools used in all projects. Referenced in each project with svn:externals*/
   \NUnit.v2.4.8
   \NCover.v.1.5.8
   \<other similar tools>
\commonFiles /*settings strong name keys etc.*/
   \ReSharper.settings
   \VisualStudio.settings
\trash /*each member of the team has trash for samples, experiments etc*/
   \user1
   \user2
\projects
   \Solution1 /*Single actual project (Visual Studio Solution)*/
      \trunk
         \src
             \Project1 /*Each sub-project resulting in single .dll or .exe*/
             \Project2
         \lib
         \tools
         \tests
         \Solution1.sln
      \tags
      \branches
   \Solution2
      \trunk
         \src
             \Project3 /*Each sub-project resulting in single .dll or .exe*/
             \Project1 /*Project1 from Solution1 references with svn:externals*/
         \lib
         \tools
         \tests
         \Solution2.sln
      \tags
      \branches

Чтобы очистить словарный запас: решение означает один продукт, Project - это проект Visual Studio (в результате получается один файл .dll или один .exe)

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

Что вы думаете об этом макете? Особенно об использовании svn: externals. Это не идеальное решение, но, учитывая все плюсы и минусы, это лучшее, что мы могли придумать. Как бы ВЫ это сделали?

Кшиштоф Козьмич
источник
Вы уверены, что имеете в виду "трэш"? А точнее «мусор»?
ssc

Ответы:

92

Если вы будете следовать моим рекомендациям, приведенным ниже (я делал это годами), вы сможете:

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

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

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

- строить и работать с любой комбинацией проектов, поскольку они независимы

- создавать и работать с несколькими копиями / версиями одного проекта, поскольку они независимы

- Избегайте загромождения репозитория системы управления версиями сгенерированными файлами или библиотеками

Рекомендую (вот говядина):

  1. Определите каждый проект для создания одного основного конечного результата, например .DLL, .EXE или .JAR (по умолчанию в Visual Studio).

  2. Структурируйте каждый проект как дерево каталогов с одним корнем.

  3. Создайте сценарий автоматической сборки для каждого проекта в его корневом каталоге, который будет строить его с нуля, без каких-либо зависимостей от IDE (но не препятствуйте его созданию в среде IDE, если это возможно).

  4. Рассмотрим nAnt для проектов .NET в Windows или что-то подобное в зависимости от вашей ОС, целевой платформы и т. Д.

  5. Сделайте так, чтобы каждый сценарий сборки проекта ссылался на свои внешние (сторонние) зависимости из единого локального каталога общей «библиотеки», причем каждый такой двоичный файл ПОЛНОСТЬЮ идентифицировался по версии: %DirLibraryRoot%\ComponentA-1.2.3.4.dll, %DirLibraryRoot%\ComponentB-5.6.7.8.dll.

  6. Сделайте так, чтобы каждый сценарий сборки проекта публиковал основной результат в единственном локальном общем «выходном» каталоге: %DirOutputRoot%\ProjectA-9.10.11.12.dll, %DirOutputRoot%\ProjectB-13.14.15.16.exe.

  7. Сделайте так, чтобы каждый сценарий сборки проекта ссылался на свои зависимости через настраиваемые абсолютные пути с полной версией (см. Выше) в каталогах «library» и «output», И НЕТ ГДЕ ДРУГОЕ.

  8. НИКОГДА не позволяйте проекту напрямую ссылаться на другой проект или какое-либо его содержимое - разрешайте ссылки только на основные результаты в "выходном" каталоге (см. Выше).

  9. Сделайте так, чтобы каждый скрипт сборки проекта ссылался на необходимые инструменты сборки, используя настраиваемый абсолютный путь с полной версией: %DirToolRoot%\ToolA\1.2.3.4, %DirToolRoot%\ToolB\5.6.7.8.

  10. Сделайте каждый проект сборки сценарий содержания ссылки источник по абсолютному пути относительно корневой директории проекта: ${project.base.dir}/src, ${project.base.dir}/tst(синтаксис варьируется в зависимости от инструмента сборки).

  11. ВСЕГДА требуется, чтобы сценарий сборки проекта ссылался на КАЖДЫЙ файл или каталог через абсолютный настраиваемый путь (с корнем в каталоге, указанном настраиваемой переменной): ${project.base.dir}/some/dirsили ${env.Variable}/other/dir.

  12. НИКОГДА не позволяйте сценарию сборки проекта ссылаться на НИЧЕГО с относительным путем, например .\some\dirs\hereили ..\some\more\dirs, ВСЕГДА используйте абсолютные пути.

  13. НИКОГДА не позволяйте сценарию сборки проекта ссылаться на НИЧЕГО, используя абсолютный путь, который не имеет настраиваемого корневого каталога, например C:\some\dirs\hereили \\server\share\more\stuff\there.

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

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

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

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

  18. ТРЕБУЕТСЯ каждый сценарий сборки проекта для проверки каждой из его переменных среды и прерывание с выводом значимого сообщения, если они не определены.

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

  20. УСТОЙЧИВАЙТЕСЬ перед соблазном зафиксировать ЛЮБЫЕ сгенерированные файлы в системе управления версиями - без результатов проекта, без сгенерированного источника, без сгенерированной документации и т. Д.

  21. Если вы используете IDE, сгенерируйте любые файлы управления проектом, которые вы можете, и не фиксируйте их в системе управления версиями (включая файлы проекта Visual Studio).

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

  23. Установите сервер непрерывной интеграции (машину сборки) без каких-либо инструментов разработки.

  24. Рассмотрим инструмент для управления внешними библиотеками и результатами, например Ivy (используемый с Ant).

  25. НЕ используйте Maven - это сначала сделает вас счастливыми, а в конечном итоге заставит плакать.

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

Дополнительное примечание относительно решений Visual Studio: не помещайте их в систему контроля версий! При таком подходе они вам вообще не нужны или вы можете их сгенерировать (как файлы проекта Visual Studio). Однако я считаю, что лучше оставить файлы решений отдельным разработчикам, чтобы они создавали / использовали их по своему усмотрению (но не регистрировали в системе управления версиями). Я храню Rob.slnфайл на своей рабочей станции, из которого я ссылаюсь на мои текущие проекты. Поскольку все мои проекты автономны, я могу добавлять / удалять проекты по своему желанию (что означает отсутствие ссылок на зависимости на основе проектов).

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

Когда вы реализуете непрерывную интеграцию или даже если вы просто хотите автоматизировать процесс выпуска, создайте для этого сценарий. Создайте единый сценарий оболочки, который: принимает параметры имени проекта (как указано в репозитории) и имени тега, создает временный каталог в настраиваемом корневом каталоге, проверяет источник для данного имени проекта и имени тега (путем создания соответствующий URL-адрес в случае Subversion) к этому временному каталогу, выполняет чистую сборку, которая запускает тесты и упаковывает результат. Этот сценарий оболочки должен работать с любым проектом и должен быть зарегистрирован в системе управления версиями как часть вашего проекта «инструментов сборки». Ваш сервер непрерывной интеграции может использовать этот сценарий в качестве основы для создания проектов или даже предоставить его (но вы все равно можете захотеть свой собственный).

@VonC: Вы НЕ хотите постоянно работать с "ant.jar", а не с "ant-abcdjar" после того, как вы сгорели, когда ваш скрипт сборки сломался, потому что вы неосознанно запустили его с несовместимой версией Ant. Это особенно характерно для Ant 1.6.5 и 1.7.0. Обобщая, вы ВСЕГДА хотите знать, какая конкретная версия КАЖДОГО компонента используется, включая вашу платформу (Java ABCD) и ваш инструмент сборки (Ant EFGH). В противном случае вы в конечном итоге столкнетесь с ошибкой, и ваша первая БОЛЬШАЯ проблема будет заключаться в отслеживании, какие версии ваших различных компонентов задействованы. Просто лучше решить эту проблему заранее.

Роб Уильямс
источник
6
Так много моментов для критики ... достаточно сказать, что это не универсальный рецепт! Пункты 5 и 6 в особенности неверны, когда проект большой и важно количество третьих лиц: вы хотите постоянно работать с ant.jar, а не с ant1.5.4.jar или продуктом myProduct .exe, а не 1.3.exe
VonC
5
Тем не менее, +1 за многие другие ваши замечания, которые являются действительными и высоко говорят о вашем обширном опыте по этой теме.
VonC
3
Я хотел бы услышать вашу критику и отреагировать на нее - каждый пункт основан на решении неудачных опытов с крупными проектами. Например, решение вопроса о том, какие версии представлены файлами Xxx.jar и Yyy.exe, особенно когда имеется буквально дюжина копий, на которые ссылаются.
Роб Уильямс
2
@Rob - Не могли бы вы подробнее рассказать о своей теме «внешнего антипаттерна»? Я поднял это как вопрос здесь: stackoverflow.com/questions/338824/…
Кен
3
@Makis: Вы были бы правы, ЕСЛИ №12 не был сбалансирован №13. Каждая ссылка на файл или каталог в каждом проекте должна выполняться по абсолютному пути, который начинается с настраиваемой переменной корневого каталога, например, $ {basedir} /sub/dir/file.txt в Ant.
Роб Уильямс,
3

Я считаю, что Pragmatic Version Control с использованием Subversion имеет все необходимое для организации вашего репозитория.

Фабио Гомеш
источник
7
@bal Пожалуйста, не пользуйтесь услугами сокращения URL. Это гораздо лучше , чтобы сказать : «Теперь в его второе издание: Прагматичный контроль версий с помощью Subversion »
meagar
3

Мы настроили наши так, чтобы они почти точно соответствовали тому, что вы опубликовали. Используем общую форму:

\Project1
   \Development (for active dev - what you've called "Trunk", containing everything about a project)
   \Branches (For older, still-evolving supported branches of the code)
       \Version1
       \Version1.1
       \Version2
   \Documentation (For any accompanying documents that aren't version-specific

Хотя я полагаю, что он не такой полный, как ваш пример, он хорошо сработал для нас и позволяет нам хранить вещи отдельно. Мне также нравится идея, что у каждого пользователя есть папка «Thrash» - в настоящее время проекты такого типа не попадают в систему управления версиями, и я всегда считал, что должны.

SqlRyan
источник
3
Я удивлен, что у вас есть отдельный каталог для документов, которые не меняются между версиями ... Я никогда не имел удовольствия работать над таким продуктом! :)
ARKBAN
1

Почему все это в одном репозитории? Почему бы просто не создать отдельный репозиторий для каждого проекта (я имею в виду «Решение»)?

Ну, по крайней мере, я привык к подходу «один проект на репозиторий». Мне кажется, что ваша структура репозитория слишком сложна.

А сколько проектов вы планируете поместить в один большой репозиторий? 2? 3? 10? 100?

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

А как насчет беспорядка со всеми этими номерами версий? Номера версий одного проекта выглядят как 2, 10, 11, а другого - как 1, 3, 4, 5, 6, 7, 8, 9, 12 ...

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

Рене Саарсу
источник
1. Один репозиторий - это политика компании, это изменить нельзя. 2. У нас будет около десятка решений. 3. под номерами версий вы подразумеваете ревизии? Для нас это не проблема.
Krzysztof Kozmic
Хорошая структура проекта должна игнорировать остальную часть структуры репозитория, особенно в отношении одного или нескольких репозиториев. Пожалуйста, посмотрите мой подробный ответ.
Роб Уильямс
1
Обратите внимание, что наличие нескольких репозиториев во многих (большинстве?) Инструментов управления версиями может быть ОЧЕНЬ дорого, например, при реализации безопасности.
Роб Уильямс
0

Я думаю, что основным недостатком предложенной структуры является то, что общие проекты будут версироваться только с первым решением, к которому они были добавлены (если svn: externals не выглядит более привлекательным, чем я могу себе представить). Например, когда вы создаете ветвь для первого выпуска Solution2, Project1 не будет разветвлен, поскольку он находится в Solution1. Если вам потребуется выполнить сборку из этой ветки позднее (выпуск QFE), он будет использовать последнюю версию Project1, а не версию Project1 на момент создания ветки.

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

С. Дракон 76
источник
В какой-то мере вы правы. Но мы можем обновить ссылку, если захотим. И помещать общие проекты в их собственное Решение тоже не имеет большого смысла. Хотя мне бы хотелось найти лучшее решение, чем svn: externals повсюду.
Krzysztof Kozmic
Что вы имеете в виду, говоря «обновить ссылку, если мы хотим»? Я не понимаю, как вы могли бы разветвлять Project1 (что кажется желательным всякий раз, когда вы разветвляете Solution2) без разветвления Solution1.
C. Dragon 76
Пожалуйста, ознакомьтесь с моим подробным ответом, в частности, чтобы НЕ помещать решения Visual Studio в систему контроля версий.
Роб Уильямс
0

Чтобы добавить к проблеме относительного пути:

Я не уверен, что это проблема:
просто проверьте Solution1 / trunk в каталоге с именем «Solution1», то же самое для Solution2: цель «каталогов», фактически представляющих ветки, - не отображаться после импорта в рабочую область. Следовательно, возможны относительные пути между «Solution1» (фактически «Solution1 / trunk») и «Solution2» (Solution2 / trunk).

VonC
источник
Это очень легко сломается, пожалуйста, посмотрите мой подробный ответ.
Роб Уильямс
0

RE: относительный путь и проблема с общим файлом -

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

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

Тим
источник
Если проекты ссылаются на другие проекты, это создает кошмар обслуживания, потому что зависимости растут экспоненциально, а ссылки ОЧЕНЬ хрупкие. Пожалуйста, посмотрите мой подробный ответ.
Роб Уильямс
0

У меня аналогичная планировка, но мой ствол, ветки, метки полностью вверху. Итак: / trunk / main, / trunk / utils, / branch / release / и т. Д.

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

Питер Мортенсен
источник