命令行参考

本章内容适用于下列用户:

1. Subversion 和 CVS 对照表

比较项目

CVS

Subversion

服务器端存储

 

  • 与客户端一一对应的目录结构

  • *,v 文件,与实际文件对应

  • CVSROOT 目录

  • 记录每次提交事务的文本数据库

  • 文件数量和提交次数有关

  • hooks 目录

(!) 如何备份版本库?

工作目录结构

  • CVS 目录

  • 用于状态保持(商业软件借助服务器端的状态保持及其弊病)

  • CVS/Entries,CVS/Root, CVS/Repository 文件(特殊情况需要手动修改)

  • .svn 目录

  • 用于状态保持(商业软件借助服务器端的状态保持及其弊病)

  • .svn/entries 文件

  • Pristine Copies存储于.svn/text-base 目录下

(!) 尝试复制、移动工作目录

版本号

  • 每个文件独立的版本号演进

  • 不存在全局版本号

  • 用 tag 创建全局版本

  • cvs log 查看文件版本

  • cvs st -v 查看 分支和tag

  • 全局版本号连续,文件版本号不连续

  • 特殊版本号: HEAD, BASE, COMMITTED, PREV

  • 日期: --revision {2002-02-17}

  • svn log, svn info, svn ls

协议

  • cvs -d :pserver:user@hostname:repos_path login

  • cvs -d :pserver:user@hostname:repos_path logout

  • svn ls http://localhost/svn/project

  • svn ls https://localhost/svn/project

  • svn ls svn://localhost/project

  • svn ls file:///repos/project/

  • svn --version 命令查看协议支持情况

创建版本库

  • cvs -d /repos/path init

  • svnadmin create /repos/path

权限设置

  • CVSROOT/passwd 文件

  • CVSROOT/avail 文件

  • 口令文件

  • LDAP认证

  • Authz授权文件

脚本扩展

  • CVSROOT 下脚本

  • hooks 下脚本

(!) SVN 有几个钩子脚本?

批量导入

  • cvs import -m message repository vendor-tag release-tags <localdir>

  • svn import /tmp/dir file:///path/to/repos -m "initial import"

  • (!) import 和 add 的区别?

    • import = add + commit

    • import != checkout

显示模块/项目列表

  • cvs co –c

(!) 需要手工设置 CVSROOT/modules

  • svn ls REPOS

(!) 服务器本身即支持

检出

  • cvs -d Repos co -d LocalDir module

  • svn co Repos/module LocalDir

添加文件和目录

  • cvs add

  • 若要取消添加:手动编辑 Entries

  • cvs ci 命令完成提交

  • svn add

  • 若要取消添加: svn revert

  • svn ci 命令完成提交

查看每一行的更改信息

  • cvs annotate filename

  • svn blame filename

(!) blame 比 annotate 更形象

文件比较

  • cvs diff -u

  • svn diff

删除文件和目录

  • cvs rm (remove)

  • 若要取消删除,编辑 Entries 文件

  • 目录不能被删除,需要用 cvs up -P 命令忽略空目录

  • svn rm (delete, del, remove)

  • 若要取消删除,执行 svn revert 即可

  • 若使用 URL 格式的Repository,则直接操纵服务器无须提交

反删除

  • cvs add 即可

(!) 直接 svn add 会怎么样? Defect or feature?

重命名

  • 客户端执行 cvs rm 和 cvs add 命令,缺点是没有保存历史

  • 服务器端直接修改对应的 *,v 文件名,缺点是破坏历史

  • svn move (mv, rename, ren)

  • mv = add_with_history + del

提交

  • cvs commit (ci) –m message

  • svn commit (ci) –m message

查看Log

  • cvs log

  • svn log

查看分支和TAG

  • cvs status –v

  • 很难得到整体、全面的分支、tag

  • svn ls Repos/branches

  • svn ls Repos/tags

查看文件修改状态

  • cvs -q up

  • cvs -nq up

  • svn status -v

  • svn status -u (连接服务器)

更新

  • cvs up

  • svn up

(!) 不显示当前文件状态

文件状态指示符

  • A R M U P C ? 

  • (!) A:Add, R:Remove, M:Modify, U:Update, P:Patch, C:Conflict, ?:unversioned

  • A D R M C X I ? !

  • (!) R : Replace, X: eXternal, I: Ignore

  • (!) 更多标志符,详见 “svn status -h” 命令

  • (!) 如何不再显示 ? 状态

检出历史版本 / 输出到stdout

  • cvs up -p -r<rev> <filename>

(!) 检出历史版本,以免 sticky 状态

  • svn cat -r<rev> <filename>

文件复制

  • 为保留历史,需要在服务器端,管理员操作

  • svn copy (cp)

(!) 还是文件反删除的手段之一

  • svn cp -r<rev>
    http://server/svn/repos/filename@<rev> filename

(!) 参见:用合并命令还原文件

创建分支

  • cvs tag/rtag -b BranchName …

  • svn cp trunk branches/BranchName

(!) 相当于目录复制。查看一下服务器端的变化,理解SVN的轻量级分支创建

创建里程碑

  • cvs tag/rtag TagName …

  • svn cp trunk tags/TagName

(!) 相当于目录复制。查看一下服务器端的变化

口令缓存

  • ~/.cvspass 文件

  • ~/.subversion/auth

(!) 发布机上提交代码,为什么提交者不是我?

关键字扩展

  • 关键字: $Id$, $Author$, $Date$, $Revision$, …

  • 缺省支持关键字扩展,二进制文件除外

  • cvs add -kb

  • cvs up -kkv

  • 缺省关闭关键字扩展(更安全)

  • svn:keywords 属性

  • svn ps svn:keywords “Author Date Id Revision” file

  • svn pl -v filename

换行符

  • 缺省添加文件模式为文本

  • 二进制文件添加要用 -kb 参数: cvs add -kb logo.gif

  • 凡是按文本模式添加的文件,版本库中以 LF 存储换行符

  • 缺省添加文件不涉及换行符转换,即服务器忠实于客户端

  • svn ps svn:eol-style native file

  • svn ps svn:eol-style LF file

  • svn ps svn:eol-style CRLF file

(!) 更改换行符后,有时整个文件要重新提交,为什么?

分支合并

  • cvs up –j tag1 –j tag2

/!\ 需要手动记录合并动作,以免日后重复合并造成无谓冲突

  • svn merge …

  • svn mergeinfo ... (svn 1.5,实现了智能合并)

(!) 还是文件恢复/反删除的手段之一

  • svn merge –rN:M

(!) 参见:用拷贝命令反删除文件

冲突解决

  • 可能导致尚未解决的冲突被误提交

  • svn resolved 命令避免误提交

回滚

  • 有时候需要手动修改 CVS/Entries 文件(取消文件添加和删除)

  • svn revert

  • svn 此功能源自于 pristine copy

属性

  • propset (pset, ps)

  • propdel (pdel, pd)

  • propedit (pedit, pe)

  • propget (pget, pg)

  • proplist (plist, pl)

代码库整理

  • 服务器端直接操作目录树即可

  • svnadmin dump

  • svnadmin load

  • svndumpfilter

忽略文件

  • .cvsignore 文件

  • svn:ignore 属性

整合外部版本库

  • CVSROOT/modules 文件

  • svn:externals 属性

切换开发分支

  • cvs up -r

  • svn switch (sw)

服务器更换域名/IP/版本库名称

  • 重新检出

  • 或者手动修改 CVS/Entries 文件

  • svn switch --relocate 命令

2. 版本库整理相关命令

2.1. 导出 ── svnadmin dump

svnadmin dump

该命令将版本库导出到一个格式文件,该导出文件包含所有版本库历史信息,可以用于版本库备份,或导入其它版本库。

用法:

  • svnadmin dump REPOS_PATH [-r LOWER[:UPPER]] [--incremental] [-q]

参数:

  • REPOS_PATH

    必须是本地路径。如: /opt/svn/svnroot/repos2/

    -r LOWER[:UPPER]

    导出从版本 LOWER 到版本 UPPER(或仅导出 LOWER 版本,如果UPPER不提供)的版本库历史。如果不提供该参数,则导出全部历史。

    --incremental

    导出的第一个版本是和前一次版本的变更,用于增量备份和导入。如果不提供该参数,第一个导出版本是完整内容。

    -q

    在标准错误输出不显示进度 (仅错误)

    --help

    查看 svnadmin dump 命令的用法

示例:

  • svnadmin dump /opt/svn/svnroot/repos2 > dumpfile.txt -- 将版本库 repos2 导出到文件 dumpfile.txt

2.2. 导入 ── svnadmin load

svnadmin load

从标准输入读取版本库转存(导出)的格式文件,并导入到新版本库中。

用法:

  • svnadmin load [--ignore-uuid|--force-uuid] [--use-pre-commit-hook] [--use-post-commit-hook] [--parent-dir ARG] REPOS_PATH

参数:

  • REPOS_PATH

    必须是本地路径。如: /opt/svn/svnroot/repos2/。如果是空版本库(即刚刚用 svnadmin create 创建),则会用标准输入流中的 UUID 替换该库的 UUID。

    --ignore-uuid

    即使目标版本库是空的,也不用标准输入流中的 UUID 替换版本库的 UUID。

    --force-uuid

    即使目标版本库非空(含一次以上的提交),如果流中存在UUID,则设定为版本库的 UUID。

    --use-pre-commit-hook

    提交版本前调用 pre-commit 钩子

    --use-post-commit-hook

    提交版本后调用 post-commit 钩子

    --parent-dir ARG

    加载到版本库指定的目录中,缺省加载到根

    -q [--quiet]

    在标准错误输出不显示进度 (仅错误)

    --help

    查看 svnadmin load 命令的用法

示例:

  • svnadmin load --parent-dir new/subdir/for/project /opt/svn/svnroot/new_repos < dumpfile.txt

2.3. 裁减 ── svndumpfilter

svndumpfilter

从标准输入读取版本库转存(导出)的格式文件,并导入到新版本库中。

用法:

  • svndumpfilter help [include] [exclude]
    svndumpfilter exclude PATH_PREFIX ... [OPTIONS ...]
    svndumpfilter include PATH_PREFIX ... [OPTIONS ...]

子命令:

  • exclude

    从标准输入中排除某个/某些路径下的内容,仅输出其它未指定路径下的内容。

    include

    仅从标准输入中包含某个/某些路径下的内容,其它未指定的路径下的内容被抛弃。

    help

    查看帮助。后面提供 include 或者 exclude 参数,则输出 include 或 exclude 子命令的详细帮助。

参数:

  • PATH_PREFIX ...

    路径前缀。可以是空格分隔的多个前缀,将对 svn 导出文件中属于该前缀之下路径的文件或者目录进行相应的处理(忽略或者包含)。前缀如果不包含"/",将会自动添加一个"/"。

    --drop-empty-revs

    删除因过滤而产生的空版本。

    --renumber-revs

    过滤后重编余下的版本。

    --skip-missing-merge-sources

    跳过缺少的合并源。

    --targets ARG

    传递文件 ARG 的内容为额外的参数

    --preserve-revprops

    不过滤版本属性。

    --quiet

    不显示过滤的统计数据。

示例:

  • 将 svn 的 dump 文件 inputfile 中出现的以 /trunk/module1 或者 /trunk/module2 为前缀的文件和路径忽略,其余文件和目录转存到文件 filteredfile。

    • $ svndumpfilter --drop-empty-revs --renumber-revs --skip-missing-merge-sources exclude /trunk/module1 /trunk/module2  < inputfile > filteredfile

2.4. 导入后目录降级

导入后目录降级

即导入到一个子目录中。如旧版本库 old_repos 中的 /trunk, /tags, /branches 等目录,导入到新库 new_repos 中的新路径为 repos1/trunk, repos1/tags, repos1/branches。

实现目录降级非常简单:

  • 在新版本库中创建要导入到的子目录。如在新版本库 new_repos 中创建目录 repos1:

    • svn mkdir file:///opt/svn/svnroot/new_repos/repos1 -m "create new subdir for import"
  • 在使用 svnadmin load 导入时,提供参数 --parent-dir DIR_NAME。如导入到新库的 repos1 目录:

    • svnadmin load --parent-dir repos1 /opt/svn/svnroot/new_repos < old_repos_dumpfile

2.5. 导入后目录升级

导入后目录升级

即从旧版本的一个子目录的导出内容,导入到一个新版本库的根目录中。如旧版本库 old_repos 中的 repos1/trunk, repos1/tags, repos1/branches 等目录,导入到新库 new_repos 中的新路径为 trunk, tags, branches。

实现目录升级稍微复杂,需要对导出文件进行替换操作。

  • 将旧版本的 repos1 模块下的文件(repos1/trunk, repos1/tags, repos1/branches)导出:

    • $ svnadmin dump /opt/svn/svnroot/old_repos | svndumpfilter include /repos1 --drop-empty-revs --renumber-revs > filteredfile
      版本被重新编号如下:
         10 => 7
         9 => 6
         8 => 5
         7 => 4
         6 => 3
         5 => 2
         4 => (丢弃)
         3 => 1
         2 => (丢弃)
         1 => (丢弃)
         0 => 0
  • 将导出文件 filteredfile 中的路径 repos1 替换为空。

    • sed -e "s@^\(Node-path: \|Node-copyfrom-path: \)repos1/@\1@"  filteredfile > filteredfile.fixed
  • 用替换过的导出文件,导入到新库。如导入到 new_repos 版本库:

    • svnadmin load /opt/svn/svnroot/new_repos < filteredfile.fixed
  • 删除新库中可能包含的 /repos1

    • (!) 如果要避免在新库中出现 /repos1 空目录,在导出旧版本库时使用 --revision X:Y 参数。X 是创建 /repos1 目录后的下一个版本,Y是版本库最新版本。

3. 版本库转换相关命令

3.1. cvs2svn

cvs2svn

将 CVS 的版本库转换为 Subversion 的版本库,并保持全部历史数据,包括里程碑和分支。

  • cvs2svn 可以将 CVS 库直接转换并导入到一个新的 Subversion 版本库中

  • cvs2svn 还可以将 CVS 版本库导出到一个文件中,该文件和 svnadmin dump 导出文件格式相同。 {OK} 推荐使用该方法。

用法:

  • cvs2svn [OPTION...] OUTPUT-OPTION CVS-REPOS-PATH

    即 cvs2svn 除可选参数外,需要指定 输出选项CVS版本库路径

CVS版本库路径:

CVS-REPOS-PATH

CVS 版本库的绝对路径。如: /cvshome/project1

输出选项: 输出选项包含一系列参数设置,用于设定CVS版本库转换后转存在一个导出文件,还是直接导入版本库中。

  • 导入到版本库(不推荐):

    -s, --svnrepos=PATH

    直接导入到 SVN 版本库中。SVN 版本库由 <PATH> 指定

    --existing-svnrepos

    导入到由 --svnrepos 设定的已经存在的版本库中,否则创建一个新的版本库。版本库名称已经由 --svnrepos 进行设定。

  • 导入到文件(推荐):

    --dumpfile=PATH

    导出到文件

可选参数

  • 换行符转换策略

    • 缺省不进行转换。即所有文件不设置 svn:eol-style。优点是:安全,不会造成误判。缺点是:转换为 SVN 版本库后,在 Windows 上检出,文件换行符都是LF的 Unix 格式换行符。

    • 使用 --default-eol=native 参数

      • 使用 --default-eol=native,将自动为 CVS 中非二进制文件设置属性 svn:eol-style 为 native。

      • 缺点: 如果 CVS 某些二进制文件(如 .gif 文件)没有设置 -kb 模式,将会造成灾难,数据损坏。

    • 使用 --auto-props, --mime-types, 和 --eol-from-mime-type 参数精细调整换行符

      --eol-from-mime-type

      根据文件的 mime type 设置 svn:eol-style。与 --mime-types=FILE 或者 --auto-props 配合使用有效。

      --auto-props=FILE

      参考自动属性设置为文件设置属性和换行符标记,指定的文件为 svn 配置文件,包含 auto-props 小节。

      --mime-types=FILE

      指定一个 apache 风格的 mime.types 文件用于参照设定 svn:mime-type。如果还使用了 --eol-from-mime-type 参数,则参照扩展名确定文件的 mime-type,进而设置换行符格式

  • 字符集设置

    • --encoding=ENC 设置字符集。

    • 首先确认一下 CVS 中字符集设置: 文件名、提交说明、用户名。(文件内容除外)

      • log 的字符集。可以打开 *,v 文件,查看log 是否有乱码。一般字符集是 gbk。

      • 文件名的字符集。查看 CVS 库中的文件。如果中文文件名能够显示,则是和当前编码一致,可能已经是 UTF-8

      • log 和 文件名的字符集编码不同的原因可能是:文件复制之后,文件名自动转换为该平台的编码。而 log 是保存在文件 *,v 中,不会改变

    • 可以用多个 --encoding=ENC 参数。例如:

      • cvs2svn --dumpfile=dump.txt --encoding=utf-8 --encoding=gbk   /cvshome/project1/
    • --fallback-encoding=ENC 设置最后的防线

  • 关键字扩展?

    • 缺省将所有非 -kb 文件设置 svn:keywords 属性,值为: "author id date"

    • 如果设置 --keywords-off,则不再为任何文件设置 svn:keywords

  • 检出 CVS 模式

    • 缺省使用 --use-internal-co, 即用 cvs2svn 自己的方法检出,速度快,但是消耗磁盘空间。

    • 如果磁盘空间紧张,使用 --use-cvs 参数

    • 尽量不要使用 --use-rcs,因为可能不能正确转换中文的提交说明

  • 是否导出里程碑和分支?

    • 仅导出主线: --trunk-only

    • --exclude=REGEXP 参数排除某些里程碑/分支

    • 岐义里程碑/分支名处理。出现岐义,是因为 CVS 的里程碑/分支 创建的随意性,有可能在不同的文件存在同名的标签,一些文件的标签是里程碑,而另外一些同名的是里程碑。

      • 参数 --symbol-default=OPT, --force-branch=REGEXP, --force-tag=REGEXP, --symbol-hints=PATH, --write-symbol-info=PATH 可以选择用于处理岐义。

  • 里程碑重命名

    • --symbol-transform 参数可以实现 CVS 里程碑名称转换为新的 SVN 里程碑名称

    • 示例

      • cvs2svn --symbol-transform='([0-9])-(.*):release-\1.\2' -s /svnhome/project1 /cvshome/project1
        会实现:
          1-0 → release-1.0
          1-1 → release-1.1
          2-0 → release-2.0

示例:

  • cvs2svn --dumpfile=dump.txt  \
            --use-cvs  --encoding=utf-8 --encoding=gbk  --tmpdir=tmp  \
            --mime-types=/etc/mime.types  --eol-from-mime-type  \
            --symbol-transform='(?<=[0-9])-(?=[0-9]):.'  \
            /cvshome/project1/


群英汇帮助类