大多数subversion工具使用/ trunk,/ branches和/ tags创建默认存储库布局。该文档还建议不要为每个项目使用单独的存储库,以便可以更轻松地共享代码。
根据该建议,我得到了一个具有以下布局的存储库:
/trunk /Project1 /Project2 /branches /Project1 /Project2 /tags /Project1 /Project2
等等,你明白了。随着时间的推移,我发现这个结构有点笨拙,我发现对建议有另一种解释,例如:
/Project1 /trunk /branches /tags /Project2 /trunk /branches /tags
那么,人们使用哪种布局,为什么?或者 - 还有另一种方法可以做我完全错过的事情吗?
答案 0 :(得分:32)
我发现Subversion Repository Layout博客文章很好地总结了这一点:
(...)有几种常见的布局 已被采纳的 社区作为最佳做法和 因此可以将这些视为 建议。如果您的存储库是 以下是公众可以访问的 这些约定可能会使它更容易 对于已访问其他用户的用户 Subversion存储库找到了什么 他们正在寻找。
有两种常用的布局:
trunk branches tags
第一种布局是最佳选择 对于包含a的存储库 单个项目或一组项目 与每个人紧密相关 其他即可。这种布局很有用,因为 分支或标记它很简单 整个项目或一组项目 用一个命令:
svn copy url://repos/trunk url://repos/tags/tagname -m "Create tagname"
这可能是最常见的 使用的存储库布局和使用 很多开源项目,比如 Subversion本身和Subclipse。这个 是大多数托管网站的布局 像Tigris.org,SourceForge.net和 Google代码跟随每个项目 这些网站是自己的 库中。
下一个布局是最佳选择 包含无关的存储库 或松散相关的项目。
ProjectA trunk branches tags ProjectB trunk branches tags
在此布局中,每个项目都会收到 一个顶级文件夹,然后是 trunk / branches / tags文件夹 在它下面创造。这真的是 与第一个布局相同的布局,它是 只是而不是把每个 他们在自己的存储库中项目 都在一个存储库中。该 Apache Software Foundation使用它 他们的存储库的布局 包含他们所有的项目 单一存储库。
通过这种布局,每个项目都有它 自己的分支和标签很容易 为其中的文件创建它们 项目使用一个命令,类似于 之前显示的那个:
svn copy url://repos/ProjectA/trunk url://repos/ProjectA/tags/tagname -m "Create tagname"
你不能轻易做到这一点 layout是创建一个分支或标记 包含来自ProjectA和的文件 项目B。你仍然可以做到,但它 需要多个命令和你 还必须决定你是否要去 为...创建一个特殊的文件夹 分支和标签涉及 多个项目。如果你要去 需要做很多事,你可能想要 考虑第一个布局。
所以,换句话说:
整篇文章值得一读。
答案 1 :(得分:8)
第二种布局是要走的路。一个很好的理由是允许或拒绝开发人员使用其中一个项目。
答案 2 :(得分:5)
我更喜欢第二个。第二,如果两个项目的人员权限不同,则更容易实现。
答案 3 :(得分:2)
我非常喜欢第二种,如果需要,可以使用maven或ant / ivy从其他项目中摄取工件。
我还希望每个存储库或少量相关存储库都有一个项目。
它简化了访问控制,这在存储库级别比存储库中的路径级别更容易 - 特别是在针对LDAP进行身份验证时。
备份/恢复操作最初有点复杂,因为您必须遍历所有存储库才能执行热拷贝,但在不幸的事件中,您只需要还原一个存储库 - 其他存储库不需要脱机或松散任何数据。随着项目的消亡,可以简单地删除存储库,从而为将来的备份节省空间。
当每个存储库只有一个项目(或少量相关项目)时,Hook脚本变得更简单,您不必检查受影响的路径以有条件地在钩子中执行操作。
正如retracile指出的那样,如果您想要使用svndumpfilter选择性地导出,那么一个整体存储库可能会非常痛苦 - 导致其死亡的更改路径的数量可能很高。
为svn的未来版本升级存储库架构需要更多的努力 - 你必须 n 次而不是一次......但它可以编写脚本,你不需要一次协调所有人
如果有人提交密码,你必须删除密码,你可以在一个仓库中快速进行转储/过滤/重新加载,同时不影响其他团队。
如果你采用这条路线,那么有一条建议 - 每个仓库有一个不同的.conf文件而不是一个巨大的文件,再次管理更容易,并且提供一些时间戳会变旧的安慰 - 如果有什么不对劲你可以更容易地寻找最近的变化。
答案 4 :(得分:1)
我决定咬紧牙关并重新构建我的存储库。我写了一个小程序来帮忙(下面)。我遵循的步骤是:
svn checkout
整个存储库。这需要很长时间和大量磁盘空间。 svn delete
过时的主干,标记和分支文件夹)svn commit
返回存储库。整个过程需要时间,但我决定采用这种方法,因为修改工作副本比黑客攻击实时存储库要安全得多,而且如果一切都出错,我可以选择简单地丢弃工作副本,修复工作副本中的任何问题,并将整个重组作为单个修订提交。
这是我用来移动的C#代码。需要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");
}
}
}
答案 5 :(得分:0)
请参阅svnbook中的Repository Layout
有一些标准的,推荐的方法来组织内容 存储库。大多数人创建一个trunk目录来保存“main” “开发行”,包含分支副本的分支目录, 以及包含标签副本的标签目录。
/ trunk/ branches/ tags/
如果存储库包含多个项目,则管理员通常会编制索引 他们按项目布局。
这是一个这样的布局的例子:
/ paint/ trunk/ branches/ tags/ calc/ trunk/ branches/ tags/
当然,您可以自由地忽略这些常见布局。你可以创建 任何类型的变化,无论对您或您的团队最有效。 请记住,无论您选择什么,它都不是永久的承诺。 您可以随时重新组织您的存储库。因为分支和 标签是普通目录,svn move命令可以移动或重命名 但是你希望他们。从一种布局切换到另一种布局只是一个 发布一系列服务器端移动的问题;如果你不喜欢 事情在存储库中组织,只是玩杂耍 周围的目录。
请记住,虽然移动目录很容易,但是 需要考虑其他用户。你的杂耍可以 使用现有工作副本的用户迷失方向。如果用户有工作 特定存储库目录和svn move子命令的副本 从最新修订版中删除路径,然后在用户下一步时删除 运行svn update,她被告知她的工作副本代表一条路径 不再存在。然后她被迫转向新的 位置。