作者:Zoom.Quiet

1. 概述

本文包含了创建和使用Subversion 进行软件开发的基本知识,为有志于使用Subversion 这一方便的版本管理工具来支持规范化团队软件开发的程序员,在进行分布式协同开发时,如何组织版本控制提供了基础的建议和实用技巧;

2. 简介

Subversion:
  • 简称SVN 是 http://subversion.tigris.org/ 社区开发的,一个流行的用以代替CVS 的高效版本管理系统;和CVS 类似,也是一种"中央仓库式"的版本管理系统;不过,和CVS 相比 SVN 具有很多高级特性;
  • 详细的信息,可以参考在线的 SVNBookv1.4

3. 安装SVN

当前最新版本是 1.5.5, SVN支持在各种操作系统中运行,安装前请从官方网站下载对应版本; 本文将以 Ubuntu 系统为例进行说明.

3.1. 环境准备

一个 7.04 以上版本的Ubuntu 环境,有root 权限即可;

3.2. 安装测试

因为SVN 已经包含在 Ubuntu 软件仓库中,安装SVN 仅需一个命令:

$ sudo apt-get install subversion

如果系统报告了依赖关系的错误,请找出相应的软件包并安装它们。如果存在其它问题,也请自行解决。如果您是再不能解决这些问题,可以考虑通过 Ubuntu 的网站、Wiki、论坛或邮件列表寻求支持。

3.3. 运营发布

SVN 可以提供多种协议的访问渠道,以下是模式列表:

模式 访问方法
file:/// 直接访问本地硬盘上文件仓库
http:// 通过 WebDAV 协议访问支持 Subversion 的 Apache 2 Web 服务器
https:// 类似 http://,支持 SSL 加密
svn:// 通过自带协议访问 svnserve 服务器
svn+ssh:// 类似 svn://,支持通过 SSH 通道
  • 其中svn:// 是本文介绍的模式;
  • 要想使用SVN,首先要初始化一个版本仓库:
    $ svnadmin create /path/to/svn/myproj
    
  • 然后,运行`svnserve`
    $ svnserve -d -r /path/to/svn
    
    • 这样,所有 `/path/to/svn` 目录中的SVN仓库都可以通过 svn:// 协议进行远程访问了
      # 本地访问
      $ svn co svn://localhost/myproj
      # 远程访问
      $ svn co svn://host.example.org/myproj
      # 即刻下载,建立了本地工作复本,可以进行协同开发了
      

3.4. 在线免费SVN仓库

事实上在网络中有很多SVN的免费空间可以使用,其中 http://code.google.com/intl/zh/ 是一个较轻便却完备的的项目管理环境,只要注册成功一个项目空间,就同时获得了一个维基,一个Issue ~ 提案追踪环境,和一个SVN仓库;

4. 管理SVN

SVN 本身提供了丰富的管理工具, 在系统配置方面,仅仅有少量文件用以声明关键信息.

4.1. 关键配置

在仓库目录的 conf 目录中 svnserve.conf 是关键配置文件:

...
[general]
# 声明匿名用户权限 read|write
anon-access = read
# 声明登录用户权限 read|write
auth-access = write

# 声明登录用户口令信息文件
password-db = passwd.cfg
# 声明登录用户仓库访问权限
authz-db = authz.cfg
...

4.2. 权限配置

配合svnserve.conf 的声明, SVN 通过理解两个文件来对仓库的访问进行控制:

4.2.1. password-db

声明的口令文件,定义了权限用户和口令:

[users]
# 用户名=口令 的格式来逐行声明用户帐号
woodpecker = 1q2w3e4r@woodpecker.org
...

4.2.2. authz-db

声明的认证文件,定义了权限用户组和仓库不同部分的访问控制:

[groups]
# 声明用户组 repomana 包含了几个用户
repomana = woodpecker,zoomq

# 仓库目录权限声明 [仓库名:目录名] 格式引导多个权限声明
[woodpecker:/]
# * 代表任何人
* = r
# repoman 组成员可以读写
@repomana = rw

[woodpecker:/foo]
# 任何人可写
* = rw
# river 用户只读
river = r
...

5. 使用SVN

作为标准意义上的版本管理系统,SVN 和其它任何版本管理系统日常使用并没有什么巨大的不同,是一个非常容易上手的工具系统;

5.1. 日常使用

以命令行形式说明日常通过SVN 进行协同开发时最常用的操作:

  1. 更新本地工作复本:
    • $ svn up
  2. 进行一些修订:
    • $ svn add ~ 增补文件/目录
    • $ svn del ~ 删除文件/目录
    • $ svn cp ~ 复制文件/目录
    • $ svn mv ~ 移动文件/目录
    • 以上命令随时可以通过 --help 获得充分的指示,例如:
       $ svn mv --help
      move (mv, rename, ren): 在工作副本或版本库中移动或改名文件或目录。
      用法: move SRC... DST
      
      当移动多个源时,它们作为 DST 的子节点增加,DST 必须是目录。
      
        注意: 本子命令等同于先 “copy”,然后 “delete”。
        注意: 此命令中 --revision 选项没有作用,已经淘汰。
      
        SRC 可同时为工作副本(WC) 路径或 URL: 
          WC  -> WC  :  移动并加入新增调度 (连同历史记录)
          URL -> URL :  完全是服务器端更名。
        所有 SRC 必须是同一类型。
      
      有效选项: 
        -r [--revision] ARG      : ARG (一些命令也接受ARG1:ARG2范围)
                                   版本参数可以是如下之一: 
                                      NUMBER       版本号
                                      '{' DATE '}' 在指定时间以后的版本
                                      'HEAD'       版本库中的最新版本
                                      'BASE'       工作副本的基线版本
                                      'COMMITTED'  最后提交或基线之前
                                      'PREV'       COMMITTED的前一版本
        -q [--quiet]             : 不打印信息,或只打印概要信息
        --force                  : 强制操作运行
        --parents                : 创建中间目录
        -m [--message] ARG       : 指定日志信息ARG
        -F [--file] ARG          : 从文件ARG读取日志信息
        --force-log              : 强制校验日志信息资源
        --editor-cmd ARG         : 使用 ARG 作为外部编辑器
        --encoding ARG           : 将ARG的值视为字符编码
        --with-revprop ARG       : 在新版本设置版本属性 ARG
                      使用格式 name[=value]
      

  3. 可能取消一些修改
    • $ svn revert
    • 详细帮助:
      revert: 将工作副本文件恢复到原始版本(恢复大部份的本地修改)。
      用法: revert PATH...
      
        注意: 本子命令不会访问网络,它解除任何冲突的状态。
        但是,它不恢复被删除的目录。
      
      有效选项: 
        --targets ARG            : 传递文件 ARG 内容为附件参数
        -R [--recursive]         : 向下递归,与 --depth=infinity 相同
        --depth ARG              : 受深度参数 ARG(“empty”,“files”,“immediates”,或“infinity”) 约束的操作
        -q [--quiet]             : 不打印信息,或只打印概要信息
        --changelist ARG         : 只能对修改列表 ARG 成员操作
                                   [aliases: --cl]
      
      

  4. 可能解决一些冲突:
    • $ svn resolved
    • 详细说明:
      resolved: 删除工作副本中目录或文件的“冲突”状态。
      用法: resolved PATH...
      
        注意: 本子命令不会依语法来解决冲突或是删除冲突标记;它只是删除冲突相关的
              附加文件,让 PATH 可以被再次提交。它已经过时,被
              “svn resolve --accept working”取代。
      
      有效选项: 
        --targets ARG            : 传递文件 ARG 内容为附件参数
        -R [--recursive]         : 向下递归,与 --depth=infinity 相同
        --depth ARG              : 受深度参数 ARG(“empty”,“files”,“immediates”,或“infinity”) 约束的操作
        -q [--quiet]             : 不打印信息,或只打印概要信息
      
    • 可能的情景:
      $ svn up
      C  sandwich.txt
      Updated to revision 2.
      $ ls -1
      sandwich.txt
      sandwich.txt.mine
      sandwich.txt.r1
      sandwich.txt.r2
      
      • 在这种情况下,SVN不会允许你提交sandwich.txt,直到你解决冲突,可选的处置是:
        1. “手动”合并冲突文本(检查和修改文件中的冲突标志)
        2. 运行svn revert <filename>来放弃所有的本地修改
        3. 用某一个版本的 临时文件覆盖你的工作文件
          • <filename>.r* 代表的是文件的第几个版本
          • <filename>.mine 代表的是本地我的文件版本
          • <filename> 是包含冲突标识的提示文件

  5. 提交修改:
    • $ svn ci -m "提交理由"

      然后,就是以上过程的不断循环

5.1.1. 对于 CVS 用户

特别的,对于从CVS系统迁移过来的用户,需要提升一些关键概念,来更好的使用 SVN:

  1. 版本号不同了
    • 在CVS中,修订版本号是每文件的,这是因为CVS使用RCS文件保存数据,每个文件都在版本库有一个对应的RCS文件,版本库几乎就是根据项目树的结构创建。
    • 在Subversion,版本库看起来像是一个单独的文件系统,每次提交导致一个新的文件系统;本质上,版本库是一堆树,每棵树都有一个单独的修订版本号。当有人谈论“修订版本54”时,他们是在讨论一个特定的树(并且间接来说,文件系统在提交54次之后的样子)。
    • 技术上讲,谈论“文件foo.c的修订版本5”是不正确的,相反,一个人会说“foo.c在修订版本5出现”。同样,我们在假定文件的进展时也要小心,在CVS,文件foo.c的修订版本5和6一定是不同的,在Subversion,foo.c可能在修订版本5和6之间没有改变。
    • 类似的,在CVS中标签或分支是文件的一种标注,或者是单个文件的版本信息,而在Subversion中,标签和分支是整个目录树的拷贝
    • 版本库作为一个整体,每个文件的许多版本可见:每个分支的最新版本,每个标签的最新版本以及trunk本身的最新版本。所以,我们再精炼一下术语,我们说“foo.c在修订版本5出现在/branches/REL1”
  2. 目录有版本了
    • 因为 SVN 的版本是针对整个仓库的变迁,所以:
      1. svn addsvn delete现在也工作在目录上了,就像在文件上一样,还有svn copysvn move也一样;然而,这些命令不会导致版本库即时的变化,相反,工作的项目只是“预定要”添加和删除,在运行svn commit之前没有版本库的修改
      2. 目录不再是哑容器了;它们也有文件一样的修订版本号(更准确一点,谈论“修订版本5的目录foo/”是正确的)

  3. 状态丰富并合理了
    • 在Subversion,已经设法抹去cvs statuscvs update之间的混乱。
    • cvs status命令有两个目的:
      • 第一,显示用户在工作拷贝的所有本地修改,
      • 第二,显示给用户哪些文件是最新的。
    • 很不幸,因为CVS难以阅读的状态输出,许多CVS用户并没有充分利用这个命令的好处。相反,他们慢慢习惯运行cvs updatecvs -n update来快速查看区别,如果用户忘记使用-n选项,副作用就是将还没有准备好处理的版本库修改合并到工作拷贝。
    • 对于Subversion,通过修改svn status的输出使之同时满足阅读和解析的需要来努力消除这种混乱,同样,svn update只会打印将要更新的文件信息,而不是本地修改
    • 详细说明:
      status (stat, st): 显示工作副本中目录与文件的状态
      用法: status [PATH...]
      
        未指定参数时,只显示本地修改的条目(没有网络访问)。
        使用 -q 时,只显示本地修改条目的摘要信息。
        使用 -u 时,增加工作版本和服务器上版本过期信息。
        使用 -v 时,显示每个条目的完整版本信息。
      
        输出的前六栏各占一个字符宽度: 
          第一栏: 表示一个项目是增加、删除,还是修改
            “ ” 无修改
            “A” 增加
            “C” 冲突
            “D” 删除
            “I” 忽略
            “M” 改变
            “R” 替换
            “X” 未纳入版本控制,但被外部项目所用
            “?” 未纳入版本控制
            “!” 该项目已遗失(被非 svn 命令删除)或不完整
            “~” 版本控制下的项目与其它类型的项目重名
          第二栏: 显示目录或文件的属性状态
            “ ” 无修改
            “C” 冲突
            “M” 改变
          第三栏: 工作副本目录是否被锁定
            “ ” 未锁定
            “L” 锁定
          第四栏: 已调度的提交是否包含副本历史
            “ ” 没有包含
            “+” 包含
          第五栏: 该条目相对其父目录是否已切换
            “ ” 正常
            “S” 已切换
          第六栏: 版本库锁定标记
            (没有 -u)
            “ ” 没有锁定标记
            “K” 存在锁定标记
            (使用 -u)
            “ ” 没有在版本库中锁定,没有锁定标记
            “K” 在版本库中被锁定,存在锁定标记
            “O” 在版本库中被锁定,锁定标记在一些其他工作副本中
            “T” 在版本库中被锁定,存在锁定标记但已被窃取
            “B” 没有在版本库中被锁定,存在锁定标记但已被终止
      
        是否过期的信息出现的位置是第八栏(与 -u 并用时): 
            “*” 服务器上有更新版本
            “ ” 工作副本是最新版的
      
        剩余的栏位皆为变动宽度,并以空白隔开: 
          工作版本号(使用 -u 或 -v 时)
          最后提交的版本与最后提交的作者(使用 -v 时)
          工作副本路径总是最后一栏,所以它可以包含空白字符。
      
        范例输出: 
          svn status wc
           M     wc/bar.c
          A  +   wc/qax.c
      
          svn status -u wc
           M           965    wc/bar.c
                 *     965    wc/foo.c
          A  +         965    wc/qax.c
          Status against revision:   981
      
          svn status --show-updates --verbose wc
           M           965       938 kfogel       wc/bar.c
                 *     965       922 sussman      wc/foo.c
          A  +         965       687 joe          wc/qax.c
                       965       687 joe          wc/zig.c
          Status against revision:   981
      
      有效选项: 
        -u [--show-updates]      : 显示更新信息
        -v [--verbose]           : 打印附加信息
        -N [--non-recursive]     : 过时;尝试 --depth=files 或 --depth=immediates
        --depth ARG              : 受深度参数 ARG(“empty”,“files”,“immediates”,或“infinity”) 约束的操作
        -q [--quiet]             : 不打印信息,或只打印概要信息
        --no-ignore              : 忽略默认值和 svn:ignore 属性
        --incremental            : 给予适合串联的输出
        --xml                    : 输出为 XML
        --ignore-externals       : 忽略外部项目
        --changelist ARG         : 只能对修改列表 ARG 成员操作
                                   [aliases: --cl]
      

  4. 分支和标签自然了
    • Subversion不区分文件系统空间和“分支”空间;分支和标签都是普通的文件系统目录,这恐怕是CVS用户需要逾越的最大心理障碍;-)
    • 带来的好处是 分支自然可见了!标签不必要了!
      • 开辟分支,只是将目录复制到约定的分支容器中,比如说:
        • $ svn cp trunk branches/my-proj-branch_0.1
      • 在CVS 中作为changeset(修订集)来使用的标签 在SVN 中,版本号天然就包含了这一特性, 完全可以用版本号来当 标签用!
    • 注意:
      因为Subversion把分支和标签看作普通目录看待,一直要记住检出项目的trunk(http://svn.example.com/repos/calc/trunk/),
      而不是项目本身的(http://svn.example.com/repos/calc/)。
      如果你错误的检出了项目本身,你会紧张的发现你的项目拷贝包含了所有的分支和标签
      

5.1.2. 迁移 CVS 到 SVN

  • 要享用SVN 带来的便利,最直接的方法就是迁移原先的版本仓库到SVN来;
  • 最流行的(好像是最成熟的)转化工具是cvs2svn(http://cvs2svn.tigris.org/),它是最初由Subversion自己的开发社区成员开发的一个Python脚本:它会多次扫描你的CVS版本库,并尽可能尝试推断提交,分支和标签,当它结束时,结果是可以代表代码历史的Subversion版本库或可移植的Subversion转储文件,关于指令和警告的详细信息可以看官方网站.

5.2. 客户端

SVN 有丰富的客户端软件可以选择,一般命令行内置工具已经足够好用,但是对习惯窗口界面的人,SVN 也有很多选择,其中最稳定和友好的是官方社区创建的:

  • TortoiseSVN
    • 这是和Windows 资源管理器紧密结合的工具,所有操作都包含在右键菜单中;
    • 同时也包含了 合并,diff查阅,远程仓库浏览器 等等丰富的支持;
    • 而且支持世界上大多数地区语言的界面;

      建议Windows 中的用户下载体验;

5.3. 高级管理

SVN 作为成熟的版本管理系统,可以支持各种级别的开发支持; 当面对大型复杂系统开发时,作为基础配置管理支持系统,必须拥有一些高级功能来支撑复杂业务,这里介绍几方面常用知识;

5.3.1. 常用分支模式

  • 版本控制在软件开发中广泛使用,这里是团队里程序员最常用的两种分支/合并模式的介绍,如果你不是使用Subversion软件开发,可随意跳过本小节,如果你是第一次使用版本控制的软件开发者,请更加注意,以下模式被许多老兵当作最佳实践,这个过程并不只是针对Subversion,在任何版本控制系统中都一样,但是在这里使用Subversion术语会感觉更方便一点。

5.3.1.1. 发布分支

  • 大多数软件存在这样一个生命周期:编码、测试、发布,然后重复。这样有两个问题,第一,开发者需要在质量保证小组测试假定稳定版本时继续开发新特性,新工作在软件测试时不可以中断,第二,小组必须一直支持老的发布版本和软件;如果一个bug在最新的代码中发现,它一定也存在已发布的版本中,客户希望立刻得到错误修正而不必等到新版本发布。
  • 这是版本控制可以做的帮助,典型的过程如下:
    1. 开发者提交所有的新特性到主干。 每日的修改提交到/trunk:新特性,bug修正和其他。
    2. 这个主干被拷贝到“发布”分支。 当小组认为软件已经做好发布的准备(如,版本1.0)然后/trunk会被拷贝到/branches/1.0。
    3. 项目组继续并行工作,一个小组开始对分支进行严酷的测试,同时另一个小组在/trunk继续新的工作(如,准备2.0),如果一个bug在任何一个位置被发现,错误修正需要来回运送。然而这个过程有时候也会结束,例如分支已经为发布前的最终测试“停滞”了。
    4. 分支已经作了标签并且发布,当测试结束,/branches/1.0作为引用快照已经拷贝到/tags/1.0.0,这个标签被打包发布给客户。
    5. 分支多次维护。当继续在/trunk上为版本2.0工作,bug修正继续从/trunk运送到/branches/1.0,如果积累了足够的bug修正,管理部门决定发布1.0.1版本:拷贝/branches/1.0到/tags/1.0.1,标签被打包发布。

      整个过程随着软件的成熟不断重复:
    • 当2.0完成,一个新的2.0分支被创建,测试、打标签和最终发布,
    • 经过许多年,版本库结束了许多版本发布,进入了“维护”模式,许多标签代表了最终的发布版本。

5.3.1.2. 特性分支

  • 一个特性分支是本章中那个重要例子中的分支,你正在那个分支上工作,而Sally还在/trunk继续工作,这是一个临时分支,用来作复杂的修改而不会干扰/trunk的稳定性,不象发布分支(也许要永远支持),特性分支出生,使用了一段时间,合并到主干,然后最终被删除掉,它们在有限的时间里有用。
  • 还有,关于是否创建特性分支的项目政策也变化广泛,一些项目永远不使用特性分支:大家都可以提交到/trunk,好处是系统的简单—没有人需要知道分支和合并,坏处是主干会经常不稳定或者不可用,另外一些项目使用分支达到极限:没有修改曾经直接提交到主干,即使最细小的修改都要创建短暂的分支,然后小心的审核合并到主干,然后删除分支,这样系统保持主干一直稳定和可用,但是造成了巨大的负担。
  • 许多项目采用折中的方式,坚持每次编译/trunk并进行回归测试,只有需要多次不稳定提交时才需要一个特性分支,这个规则可以用这样一个问题检验:如果开发者在好几天里独立工作,一次提交大量修改(这样/trunk就不会不稳定。),是否会有太多的修改要来回顾?如果答案是“是”,这些修改应该在特性分支上进行,因为开发者增量的提交修改,你可以容易的回头检查。
  • 最终,有一个问题就是怎样保持一个特性分支“同步”于工作中的主干,在前面提到过,在一个分支上工作数周或几个月是很有风险的,主干的修改也许会持续涌入,因为这一点,两条线的开发会区别巨大,合并分支回到主干会成为一个噩梦。
  • 这种情况最好通过有规律的将主干合并到分支来避免,制定这样一个政策:每周将上周的修改合并到分支,注意这样做时需要小心,需要手工记录合并的过程,以避免重复的合并(在“手工跟踪合并”一节描述过),你需要小心的撰写合并的日志信息,精确的描述合并包括的范围(在“合并分支到另一分支”一节中描述过),这看起来像是胁迫,可是实际上是容易做到的。
  • 在一些时候,你已经准备好了将“同步的”特性分支合并回到主干,为此,开始做一次将主干最新修改和分支的最终合并,这样以后,除了你的分支修改的部分,最新的分支和主干将会绝对一致,所以在这个特别的例子里,你会通过直接比较分支和主干来进行合并:
    $ cd trunk-working-copy
    
    $ svn update
    At revision 1910.
    
    $ svn merge http://svn.example.com/repos/calc/trunk@1910 \
                http://svn.example.com/repos/calc/branches/mybranch@1910
    U  real.c
    U  integer.c
    A  newdirectory
    A  newdirectory/newfile
    …
    
    通过比较HEAD修订版本的主干和HEAD修订版本的分支,你确定了只在分支上的增量信息,两条开发线都有了分枝的修改。

5.3.2. HOOKS

和CVS 类似SVN 同样为自动化事务响应开辟有"HOOKS"~钩子脚本支持;只是更加精简和规范化了;

一般提供9类标准钩子模板:

$ ls repos/hooks/
post-commit.tmpl	  post-unlock.tmpl  pre-revprop-change.tmpl
post-lock.tmpl		  pre-commit.tmpl   pre-unlock.tmpl
post-revprop-change.tmpl  pre-lock.tmpl     start-commit.tmpl

分别响应核心的四类操作:

HOOK 触发事件 参数
start-commit 提交事务产生前 REPOS-PATH:到版本库的路径;USER:要进行提交的用户名
pre-commit 事务完成提交之前 REPOS-PATH:版本库的路径;TXN-NAME正在提交的事务名称
post-commit 事务完成后 REPOS-PATH:到版本库的路径;REV:被创建的新的修订版本号
pre-revprop-change 修订版本属性变更前 REPOS-PATH:到版本库的路径;REVISION:要修改属性的修订版本;USER:经过认证的用户名;ACTION:属性自身的名字
post-revprop-change 修订版本属性被改变之后 REPOS-PATH:到版本库的路径;REVISION:属性存在的修订版本;USER:经过校验的产生变化的用户名;ACTION:和属性自身的名字
pre-lock 尝试锁定文件时 REPOS-PATH:到版本库的路径;PATH:锁定的路径;USER:企图执行锁定的用户
post-lock 路径被锁定后执行 REPOS-PATH:到版本库的路径;USER:企图执行锁定的用户
pre-unlock 企图删除一个文件上的钩子时 REPOS-PATH:到版本库的路径;PATH:锁定的路径;USER:企图解锁的用户
post-unlock 路径被解锁后 REPOS-PATH:到版本库的路径;USER:企图解锁的用户
警告:
  • 不要尝试用钩子脚本修改事务。一个常见的例子就是在提交时自动设置svn:eol-style或svn:mime-type这类属性。这看起来是个好主意,但它会引起问题。主要的问题是客户并不知道由钩子脚本进行的修改,同时没有办法通告客户它的数据是过时的,这种矛盾会导致出人意料和不能预测的行为。
  • 作为尝试修改事务的替代,我们通过检查pre-commit钩子的事务,在不满足要求时拒绝提交。

5.3.2.1. 强制写注释

举个实用的HOOKS 脚本实例:

  • pre-commit.tmpl 重命名为:pre-commit 并修订为以下内容:
    #!/bin/sh
    
    # PRE-COMMIT HOOK
    
    REPOS="$1"
    TXN="$2"
    
    SVNLOOK=/usr/local/bin/svnlook
    $SVNLOOK log -t "$TXN" "$REPOS" | \
       grep "[a-zA-Z0-9]" > /dev/null 
    
    if [ $? != 0 ]; then
            echo "$TXN $REPOS" 1>&2
            echo "Alert! Commit message may not be empty." 1>&2
            exit 1
    fi
    
    exit 0
    
  • 然后配置可执行属性,就可以自动拒绝空注释的检入事务,并送回对应提示:"Alert! Commit message may not be empty."

5.4. 项目管理

SVN作为基础配置管理支撑系统,可以轻快的完成版本管理的全方位支持了,而且,进一步的配合Trac 可以完成项目管理的大部分流程支持!

5.4.1. Trac

Trac 是种轻型全功能项目管理环境,主要特性有:

  • 以维基为核心的内容组织
  • 以传票为核心的任务式流程
  • 提供丰富的 TrackInks 维基字符约定,可以在任何场所方便的指向 SVN版本/传票/报表等等所有Trac 内部资源
  • 类SQL语句的报表定制支持
  • 里程碑综合视图
  • 等等

    详细的敬请期待哲思手册相关文章;

    PS:

    Trac中文化项目长期由 Zoom.Quiet 团队支持,推荐体验;

6. 文档版本

  • v0.9 090308 ZoomQuiet 完成初稿
  • v0.8 090303 ZoomQuiet 完成管理SVN部分,以及日常使用大部
  • v0.7 090216 ZoomQuiet 增补文档大纲
  • v0.6 090209 ZoomQuiet 认领写作
  • v0.5 080301 zeuux 创建

动力源自:: txt2tags 生成: 2009-03-09 00:16:15 介绍 原稿