Подтвердить что ты не робот

Макет репозитория Subversion

Большинство инструментов subversion создают макет репозитория по умолчанию с /trunk,/branch и/tags. В документации также рекомендуется не использовать отдельные репозитории для каждого проекта, чтобы код мог быть более простым.

Следуя этому совету, я получил репозиторий со следующим макетом:

/trunk
      /Project1
      /Project2
/branches
         /Project1
         /Project2
/tags
     /Project1
     /Project2

и так далее, вы получаете идею. Со временем я нашел эту структуру немного неуклюжей, и мне пришло в голову, что есть альтернативная интерпретация рекомендаций, таких как:

/Project1
         /trunk
         /branches
         /tags
/Project2
         /trunk
         /branches
         /tags       

Итак, какой макет люди используют, и почему? Или - есть ли другой способ сделать то, что я полностью пропустил?

4b9b3361

Ответ 1

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

  • Сделайте резервную копию исходного репозитория.
  • svn checkout весь репозиторий. Это заняло много времени и много места на диске.
  • Запустите программу снизу на рабочей копии с предыдущего шага.
  • Изучите измененную рабочую копию и очистите все оставшиеся проблемы (например, svn delete устаревшие папки соединительных линий, тегов и ветвей)
  • svn commit вернуться в репозиторий.

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

Здесь код С#, который я использовал для перемещения. Требуется библиотека SharpSvn.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text;
using SharpSvn;

/**
 * 
 * Program operation:
 * 1. Parse command line to determine path to working copy root
 * 2. Enumerate folders in the /trunk 
 * 3. Restructure each project folder in /trunk
 * 
 * 
 * Restructure a Project:
 * 1. Get the project name (folder name in /trunk/{Project})
 * 2. SVN Move /trunk/{Project} to /{Project}/trunk
 * 3. Reparent Project, branches
 * 4. Reparent Project, tags
 * 
 * Reparent(project, folder)
 * If /{folder}/{Project} exists
 *   SVN Move /{folder}/{Project} to /{Project}/{Folder}
 * else
 *   Create folder /{Project}/{Folder}
 *   SVN Add /{Project}/{Folder}
 * 
 **/

namespace TiGra.SvnRestructure
{
    /// <summary>
    /// Restructures a Subversion repository from
    ///     /trunk|branches|tags/Project
    /// to
    ///     /Project/trunk|branches|tags
    /// </summary>
    internal class Program
    {
        private static string WorkingCopy;
        private static string SvnUri;
        private static string Branches;
        private static string Tags;
        private static string Trunk;

        private static SvnClient svn;
        private static List<string> Projects;

        private static void Main(string[] args)
        {
            ProcessCommandLine(args);
            CreateSvnClient();
            EnumerateProjectsInTrunk();
            RestructureProjects();
            Console.ReadLine();
        }

        private static void RestructureProjects()
        {
            foreach (var project in Projects)
            {
                RestructureSingleProject(project);
            }
        }

        private static void RestructureSingleProject(string projectPath)
        {
            var projectName = Path.GetFileName(projectPath);
            var projectNewRoot = Path.Combine(WorkingCopy, projectName);
            bool hasBranches = Directory.Exists(Path.Combine(Branches, projectName));
            bool hasTags = Directory.Exists(Path.Combine(Tags, projectName));
            Reparent(Path.Combine(Trunk, projectName), Path.Combine(projectNewRoot, "trunk"));
            if (hasBranches)
                Reparent(Path.Combine(Branches, projectName), Path.Combine(projectNewRoot, "branches"));
            if (hasTags)
                Reparent(Path.Combine(Tags, projectName), Path.Combine(projectNewRoot, "tags"));
        }

        private static void Reparent(string oldPath, string newPath)
        {
            Console.WriteLine(string.Format("Moving {0} --> {1}", oldPath, newPath));
            svn.Move(oldPath, newPath, new SvnMoveArgs(){CreateParents = true});
        }

        private static void EnumerateProjectsInTrunk()
        {
            var list = EnumerateFolders("trunk");
            Projects = list;
        }

        /// <summary>
        /// Enumerates the folders in the specified subdirectory.
        /// </summary>
        /// <param name="trunk">The trunk.</param>
        private static List<string> EnumerateFolders(string root)
        {
            var fullPath = Path.Combine(WorkingCopy, root);
            var folders = Directory.GetDirectories(fullPath, "*.*", SearchOption.TopDirectoryOnly).ToList();
            folders.RemoveAll(s => s.EndsWith(".svn")); // Remove special metadata folders.
            return folders;
        }

        private static void CreateSvnClient()
        {
            svn = new SharpSvn.SvnClient();
        }

        /// <summary>
        /// Processes the command line. There should be exactly one argument,
        /// which is the path to the working copy.
        /// </summary>
        private static void ProcessCommandLine(string[] args)
        {
            if (args.Length != 1)
                throw new ArgumentException("There must be exactly one argument");
            var path = args[0];
            if (!Directory.Exists(path))
                throw new ArgumentException("The specified working copy root could not be found.");
            WorkingCopy = path;
            Branches = Path.Combine(WorkingCopy, "branches");
            Tags = Path.Combine(WorkingCopy, "tags");
            Trunk = Path.Combine(WorkingCopy, "trunk");
        }
    }
}

Ответ 2

Я нахожу, что сообщение Содержимое репозитория Subversion публикует это довольно хорошо:

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

Существует два широко используемых макета:

trunk
branches
tags

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

svn copy url://repos/trunk url://repos/tags/tagname -m "Create tagname"

Это, вероятно, наиболее часто используемый репозиторий и используется многие проекты с открытым исходным кодом, например Subversion и Subclipse. Эта это макет, который большинство хостинговых сайтов как Tigris.org, SourceForge.net и Google Code следует за каждым проектом в этим сайтам предоставляется собственный хранилище.

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

ProjectA
   trunk
   branches
   tags
ProjectB
   trunk
   branches
   tags

В этом макете каждый проект получает папку верхнего уровня, а затем Папки для внешних линий/ветвей/тегов созданный под ним. Это действительно такой же макет, как и первый макет, просто чтобы вместо каждого проекта в собственном репозитории, они все находятся в одном хранилище. Apache Software Foundation использует это макет для своего репозитория, который содержит все свои проекты в одном единый репозиторий.

В этом макете каждый проект имеет свои собственных ветвей и тегов, и это легко создать их для файлов в этом проекта с использованием одной команды, аналогичной ранее показанный:

svn copy url://repos/ProjectA/trunk url://repos/ProjectA/tags/tagname -m "Create tagname"

Что вы не можете легко сделать в этом layout создает ветку или тег, который содержит файлы из ProjectA и ProjectB. Вы все еще можете это сделать, но это требует нескольких команд, и вы также нужно решить, собираетесь ли вы создать специальную папку для ветвей и тегов, которые включают несколько проектов. Если вы собираетесь нужно сделать это много, вы можете захотеть для рассмотрения первого макета.

Итак, перефразируем:

  • Используйте первый макет для одного или нескольких связанных проектов.
  • Используйте второй макет для не связанных проектов.

Весь пост стоит прочитать.

Ответ 3

Второй макет - это путь. Одна из веских причин - разрешить или запретить разработчику работать с одним из проектов.

Ответ 4

Я предпочитаю второй. Во втором случае, если разрешения людей отличаются между двумя проектами, их проще реализовать.

Ответ 5

Я очень предпочитаю второй, используя maven или ant/ivy, чтобы при необходимости использовать артефакты из других проектов.

Я также предпочитаю иметь один проект для каждого репозитория или небольшое количество связанных репозиториев.

Это упрощает управление доступом, что проще на уровне репозитория, чем уровень пути в репозитории - особенно при аутентификации на LDAP.

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

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

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

Обновление схемы репозитория для будущих версий svn требует больше усилий - вы должны делать это n раз, а не один раз... но это может быть сценарий, и вам не нужно координировать все сразу.

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

Один совет, если вы идете по этому маршруту, - имеет другой файл .conf на один репо, а не один огромный, опять же легче управлять, а также обеспечивать комфорт, что некоторые временные метки будут старыми - если что-то вас не устраивает может легче искать последние изменения.

Ответ 6

Обратитесь Макет репозитория из svnbook

Существуют некоторые стандартные, рекомендуемые способы организации содержимого репозиторий. Большинство людей создают каталог соединительных линий для хранения "основного" строка "разработки, каталог веток для хранения копий ветки, и каталог тегов, содержащий теги.

/
   trunk/
   branches/
   tags/

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

вот пример такого макета:

/
   paint/
      trunk/
      branches/
      tags/
   calc/
      trunk/
      branches/
      tags/

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

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