Я знаю, что существует как минимум 10 различных способов структурировать проект в системе контроля версий. Мне любопытно, какие методы используются и какие работают для вас. Я работал с SVN, TFS и, к сожалению, с VSS. Я видел, как контроль версий реализован очень плохо и нормально, но никогда не был хорош.
Вот обзор того, что я видел.
Этот пример основан на SVN, но применим к большинству VCS (не столько к распределенному контролю версий).
ветвление отдельных проектов, входящих в состав сайта / Division / web / имя проекта / vb / src / [ствол | ветви | теги]
разветвить весь сайт, в случае, который я видел, был разветвлен весь сайт, за исключением основных компонентов. / подразделение / [ствол | ветви | теги] / web / имя проекта / vb / src /
Используйте main-line по умолчанию, переходите только при необходимости для изменений огромный.
@hhh Я добавил комментарий о распределенном управлении версиями (DVC). Может быть, кому-то будет полезен ответ о структуре в DVC?
Пример для SVN:
хобот/
ответвляться/
теги /
Ствол следует держать так, чтобы вы всегда могли вытолкнуть из него спусковой механизм. Не должно быть огромных зияющих ошибок, о которых вы знаете (конечно, рано или поздно они появятся, но это то, к чему вы должны стремиться).
Каждый раз, когда вам нужно создать новую функцию, вносите изменения в дизайн, что угодно, ветку. Отметьте эту ветку в начале. Затем, когда вы закончите с веткой, отметьте ее в конце. Это помогает слиться обратно в ствол.
Каждый раз, когда вам нужно подтолкнуть релиз, отметьте его. Таким образом, если что-то пойдет не так, вы сможете вернуться к предыдущей версии.
Эта настройка сохраняет магистраль как можно более чистой и позволяет быстро исправлять ошибки и устранять их, сохраняя при этом большую часть разработки в ветвях.
Редактировать: Для сторонних вещей это зависит. Если я могу этого избежать, у меня нет контроля версий. Я храню его в каталоге вне системы управления версиями и включаю оттуда. Для таких вещей, как jquery, я оставляю его под контролем источника. Причина в том, что это упрощает мой сценарий для нажатия. Я могу просто сделать svn export и rsync.
Я думаю, что политики и процедуры SCM, которые принимает команда, будут сильно зависеть от процесса разработки, который они используют. Если у вас есть команда из 50 человек, в которой несколько человек работают над важными изменениями одновременно, а выпуски выпускаются только каждые 6 месяцев, для каждого имеет смысл иметь свою собственную ветку, где он может работать изолированно и объединять только изменения из другие люди, когда он хочет их. С другой стороны, если вы команда из 5 человек, которые сидят в одной комнате, имеет смысл разветвляться гораздо реже.
Предполагая, что вы работаете в небольшой команде, где хорошее общение и сотрудничество, а выпуски частые, нет смысла когда-либо разветвлять IMO. В одном проекте мы просто добавили номер версии SVN в номер версии продукта для всех наших выпусков и даже не пометили. В тех редких случаях, когда в продукте обнаруживалась критическая ошибка, мы просто выполняли переход прямо из версии, которая была выпущена. Но в большинстве случаев мы просто исправляли ошибку в ветке и выпускали ее из основной ветки в конце недели, как и планировалось. Если ваши выпуски достаточно часты, вы почти никогда не столкнетесь с ошибкой, которая не может дождаться следующего официального выпуска.
Я работал над другими проектами, в которых мы никогда не смогли бы с этим справиться, но благодаря упрощенному процессу разработки и минимальным церемониям мы смогли очень эффективно использовать упрощенную политику управления версиями.
Я также упомяну, что все, что я написал, исходит из корпоративного ИТ-контекста, где есть только один производственный экземпляр данной базы кода. Если бы я работал над продуктом, который был развернут на 100 различных сайтах клиентов, методы ветвления и тегирования должны были бы быть немного более напряженными, чтобы управлять всеми независимыми циклами обновления во всех экземплярах.
What about external dependencies such a the AJAXTookit or some other 3rd party extension that's used on several projects?
Контроль версий предназначен для исходного кода, а не для двоичных файлов. Храните любые сторонние сборки / jar-файлы в отдельном репозитории. Если вы работаете в мире Java, попробуйте что-нибудь вроде Maven или Ivy. Для проектов .Net простой общий диск может работать хорошо, если у вас есть приличная политика в отношении того, как он структурирован и обновляется.
В своих проектах я всегда использую эту структуру.
- trunk
- config
- docs
- sql
- initial
- updates
- src
- app
- test
- thirdparty
- lib
- tools
- tags
- branches
Мой файл решения помещается прямо в основной каталог вместе с моими файлами сборки.
как ты разветвляешься? если вы разветвляете только папку src, как вы обрабатываете свою ветку, указывающую на более старую версию третьей стороны / lib?
Мы практикуем высококомпонентную разработку с использованием Java, у нас есть около 250 модулей в магистрали, которые имеют независимые жизненные циклы. Зависимости управляются через Maven (это лучшая практика прямо здесь), каждая итерация (раз в две недели) активно разрабатываемые модули помечаются новой версией. Трехзначные номера версий со строгой семантикой (major.minor.build - основные изменения означают обратную несовместимость, незначительные изменения означают обратную совместимость, а изменения номера сборки означают обратную и прямую совместимость). Наш конечный программный продукт - это сборка, в которую входят десятки отдельных модулей, опять же как зависимости Maven.
Мы разветвляем модули / сборки, когда нам нужно исправить ошибку или улучшить выпущенную версию, и мы не можем доставить версию HEAD. Пометка всех версий делает это легко, но ветки по-прежнему несут значительные административные издержки (в частности, синхронизацию ветвей с определенными наборами изменений HEAD), которые частично вызваны нашими инструментами, Subversion не оптимальна для управления ветвями.
Мы обнаружили, что критически важна довольно плоская древовидная структура предсказуемый в репозитории. Это позволило нам создать инструменты выпуска, которые устраняют большую часть боли и опасности ручного процесса выпуска (обновленные примечания к выпуску, компиляция проекта, выполнение модульных тестов, создание тегов, отсутствие зависимостей SNAPSHOT и т. д.). Избегайте слишком большого количества категоризации или другой логики в древовидной структуре.
Мы делаем примерно следующее:
svnrepo/
trunk/
modules/
m1/ --> will result in jar file
m2/
...
assemblies/
a1/
...
tags/
modules/
m1/
1.0.0/
1.0.1/
1.1.0/
m2/
...
assemblies/
a1/
iteration-55/
...
branches/
m1/
1.0/
...
Что касается внешних зависимостей, я не могу переоценить что-то вроде Maven: управляйте своими зависимостями как ссылками на версионные, однозначно идентифицированные двоичные артефакты в репозитории.
Для внутренней структуры модуля / проекта: придерживайтесь стандарта. Единообразие - ключ к успеху. Опять же, здесь может помочь Maven, поскольку он определяет структуру. Многие структуры хороши, пока вы их придерживаетесь.
Существует ли что-то вроде maven для .NET? Мне не удалось ничего раскопать.
NMaven специально нацелен на .NET (codeplex.com/nmaven), сам не использовал его. На работе у нас есть .NET-код, созданный с использованием обычного Maven и некоторых подключаемых модулей Visual Studio.
Похоже, хорошее начало, что мы запускаем новый проект со структурой, похожей на вашу :) Из любопытства, у вас есть общий родительский pom? Если да, то размещаете ли вы родительский pom в каталоге «modules» или как реальный каталог внутри «модулей»?
У нас есть иерархия родительских модулей, и мы обращаемся с ними так же, как с модулями: каждый из них имеет свой собственный каталог «модулей» внутри модулей. Начиная с Maven2, это, наконец, чисто возможно, поскольку родительские помы наследуются из репозитория. В Maven1 вам действительно нужно использовать относительные пути, и это становится неприятно.
Спасибо: D Еще один вопрос, если вы не против. Нам пришлось прямо сейчас переименовать модули (неправильные начальные имена), и у нас есть небольшой спор. Если, скажем, ваш «trunk / modules / m1» необходимо переименовать в «trunk / modules / m10», как вы думаете, «теги / модули / m1» следует переименовать в «tags / modules / m10» или следует «теги» / modules / m1 "сохранить и создать новый" теги / modules / m10 "?
Учитывая, что вы помечаете так, чтобы сборка воспроизводилась, и учитывая, что если вы отметили, вы, вероятно, уже выпустили артефакты со «старым» именем, я бы создал новую папку с тегами «m10» рядом со старым. В нашем случае старые модули в противном случае имели бы идентификаторы артефактов, отличные от имен их каталогов модулей, и это было бы не интуитивно понятно.
Замечу, что NMaven ушел на пенсию, а новое имя NPanday все еще находится в инкубаторе.
Скептическая нить, является ли Maven просто беспорядком, больше здесь.
Я могу понять логику отказа от размещения двоичных файлов в репозитории, но я думаю, что это также имеет огромное преимущество. Если вы хотите получить определенную ревизию из прошлого (обычно это более старый тег), мне нравится иметь все, что мне нужно, из svn checkout. Конечно, это не включает Visual Studio или .NET framework, но наличие правильной версии nant, nunit, log4net и т. д. Позволяет действительно легко перейти от оформления заказа к сборке. Таким образом, начать работу так же просто, как "svn co project", за которым следует "nant build".
Единственное, что мы делаем, - это помещаем двоичные файлы ThirdParty в отдельное дерево и используем svn: external, чтобы получить нужную нам версию. Чтобы упростить жизнь, у нас будет папка для каждой использованной версии. Например, мы можем добавить в текущий проект папку ThirdParty / Castle / v1.0.3. Таким образом, все необходимое для сборки / тестирования продукта находится внутри или ниже корня проекта. По нашему опыту, компромисс с дисковым пространством того стоит.
Мы мигрировали из плохого мира VSS с одним гигантским репозиторием (более 4G), прежде чем перейти на SVN. Мне было очень сложно создать новый репозиторий для нашей компании. Наша компания очень "старой" школы. Сложно добиться перемен. Я один из молодых разработчиков, мне 45! Я являюсь частью группы корпоративных разработчиков, которая работает над программами для ряда отделов нашей компании. В любом случае я настроил наши каталоги вот так
+ devroot
+--Dept1
+--Dept1Proj1
+--Dept2Proj2
+--Dept2
+--Dept2Proj1
+--Tools
+--Purchase3rdPartyTools
+--NLog
+--CustomBuiltLibrary
Я хотел включить возможность ветвления, но, честно говоря, это уже слишком. Пара вещей, с которыми мы все еще боремся, используя эту схему.
Поскольку все артефакты и конструкции находятся в одном дереве, мы получаем что-то вроде:
Хобот
Развертывать
Почему это было снижено? Похоже на приличную структуру, даже если это не одна из стандартных версий, которые вы видите.
Я предпочитаю мелкозернистые, очень организованные, автономные, структурированные репозитории. Существует диаграмма, иллюстрирующий общий (идеальный) подход к процессу обслуживания репозитория. Например, моя первоначальная структура репозитория (должна быть у каждого репозитория проекта):
/project
/trunk
/tags
/builds
/PA
/A
/B
/releases
/AR
/BR
/RC
/ST
/branches
/experimental
/maintenance
/versions
/platforms
/releases
PA
означает пре-альфаA
означает альфаB
означает бетаAR
означает альфа-релизBR
означает бета-релизRC
означает релиз-кандидатST
означает стабильный
Есть различия между строит и релизы.
N.x.K
, где N
и K
- целые числа. Примеры: 1.x.0
, 5.x.1
, 10.x.33
.N.M.K
, где N
, M
и K
- целые числа. Примеры: 1.0.0
, 5.3.1
, 10.22.33
.Недавно я разработал тренинг, посвященный управлению конфигурацией программного обеспечения, в котором я описываю подход к нумерации версий и почему именно эта структура репозитория является лучшей. Вот слайды презентации.
Также есть мой отвечать на вопрос о «Несколько репозиториев SVN против репозитория одной компании». Это может быть полезно, если вы затронете этот аспект структурирования репозитория в своем вопросе.
Не могли бы вы обновить ссылку на диаграмму в первом абзаце?
Пожалуйста, добавьте метку
"svn"
, что сбивает с толку пользователей git.