1. 当然,先用命令行 check out 出源码拷贝

      $ cd ~/work
      $ cvs -d :pserver:user@host:/path/to/repository co MODULE

2. 从 Emacs 开始

   几个命令都可以进入 PCL-CVS 中,例如用 cvs-examine:

      M-x cvs-examine RET path/to/MODULE RET

   RET 表示回车键;path/to/MODULE,源码复本的目录,cvs-examine 缺省为当前
   目录。此时 Emacs 打开名为 *cvs* 的缓冲,就是 PCL-CVS 的主界面。

   PCL-CVS 只是命令行 cvs 的前端界面。在 *cvs* 缓冲中的命令,基本只需要按
   一两下键盘,Emacs 将其翻译为 cvs 控制命令。每执行一次,Emacs 会在缓冲
   底部显示对应的 cvs 命令,以供参考。

3. 在 cvs 缓冲中常用的命令

   n, p   移动光标。

   f, o, RET 打开当前文件。

   M-s    列出所有文件的当前状态。
   x      在缓冲中去掉所有是 Up-To-Date 的状态的文件,这样比较干净。

   M-u    更新本地拷贝。

   U      放弃所做的改动,小心别把你没有提交的工作弄没了。

   m      标记文件,用于对多个文件同时操作。u 去掉标记并下移;Backspace
          去掉标记并上移;M-Backspace 同时去掉 buffer 中所有标记。% 用正
          则表达式标记文件。

   c      准备提交所做的改动,会弹出一个 *cvs-commit* 缓冲,用来写修改的
          日志,写完完按 C-c C-c,执行提交。如果有标记,同时对所标记的所
          有文件相库提交。

   C      和 c 类似,但是清除上次提交时留在 *cvs-commit* 缓冲中的内容,不
          过如果当前目录里的 ChangeLog 文件中有相关内容,会自动插入。

   d      有一个提示,询问用哪种方式 diff。此时常用的可能是:

          d d  或 d =,比较文件,本地拷贝和最后一次提交时的修订版;
          d h  比较本地拷贝和当前源码库中最新版;
          d b  比较本地拷贝和该文件的备份;
          d e  用 ediff 比较文件,本地拷贝和最后一次提交时的修订版。
      d y  和前一天的比较

   r      删除文件,从当前拷贝的工作目录中删除,需要提交。

   a      添加文件,添加到当前拷贝的工作目录中,需要提交。

   i      把某个文件的名字添加到 .cvsignore 文件,这样在运行 cvs 命令时,
          cvs 不再理会此文件。编辑 .cvsignore 文件,每一行一个或一类文件。
          下面是一个 .cvsignore 文件的例子。有些类型的文件 cvs 缺省就是忽
          略的,比如 .o 文件。

   t      设置 tag,提示输入 tag 名字。

   l      查看一个文件,所标记的多个文件,或目录文件的 log 信息。

   s      通过 cvs status 命令查看文件或目录的状态,会弹出一个漂亮的
          *cvs-info* 缓冲,列出文件的状态信息。

   z, q   关闭 *cvs* 缓冲。

4. cvs buffer 中几种状态的说明(括号中是此时可能需要用到的命令):

   cvs buffer 中按一下 M-s 可以列出所有文件。每个一行,分别列出了当前的
   CVS 状态、修订版和文件名。

   "Up-to-date" 文件和库中文件一致,也就是说,目前是最新的修订版,而且没
   有被改动过。(按 f 或 RET,进入文件进行编辑,l 看修改历史,+ 看 tag 信
   息)

   "Need-Update" 文件相对于源码库,不是最新的,需要更新。(M-u 更新,d h
   比较当前文件和源码库中的区别)

   "Modified" 文件已经被改动过,但还没有提交到源码库。(c/C 提交,d d 比
   较,d e 用 ediff 比较,U 放弃修改,小心使用)

   "Added" 用 cvs add 命令新添加的文件,添加了新文件只在本地有效,需要提
   交到源码库。(c/C 提交)

   "Removed" 用 cvs 的 remove 命令删除的文件,同 add 一样,需要提交到源码
   库。(c/C 提交)

   "Needs-Merge" 你编辑文件的时候,别人又向源码库提交过,因此本地的改动,
   和源码库中的需要合并。(先 M-u 更新,如果发生冲突,手工修改,再 c/C 提
   交,d b 和原来的备份比较,d h 和库中比较)

   "Conflict" 你的提交和源码库中当前的状态有冲突,需要手工修改,并再提交
   一次。(手工修改,再 c/C 提交)

   "Unknown" 源码库中没有该文件,这或许不是你想要的,或许是刚刚新建的。
   (如果想让 cvs 忽略此文件,按 i;想添加到源码库,按 a,再提交;用 r 删
   除)

   "Missing" 源码库中有,可是本地拷贝中却没有了。(M-u 更新,可以从新从源
   码库得到拷贝)

5. 用 Emacs 的前缀参数修改 cvs 命令的选项

   很多 cvs 命令可以给一个前缀参数,改变缺省的行为。多数的前缀参数都是
   C-u,而多数改变的行为,就是修改传递给 cvs 的默认选项。

   每执行一次操作,pcl-cvs 的 *cvs* 缓冲底部都会显示实际执行的 cvs 命令,
   这些命令往往带有一些参数,如何修改这些参数呢?就通过给 pcl-cvs 的命令
   加前缀 C-u。一般的,一个 C-u 只改变当前命令所用的 cvs 选项,如果前缀两
   个 C-u,则是永久改变所用选项。

   例如,d d 缺省比较当前拷贝和库中你check out时的修订版。

       如果用 C-u d d 会提示输入 cvs 的选项,此时你可以给任意的 cvs diff
       选项,用以进行各种各样灵活的比较。比如,输入 -r1.10 -r2.3 RET,此
       次比较的就是源码库中当前文件修订版 1.10 和 2.3 之间的区别。

       如果 C-u C-u d d,输入 -r1.10 RET,以后的 d d 命令都会带着 -r1.10
       仿佛永久修改了默认选项。当然,可以再 C-u C-u d d 修改回去。

   再如,cvs add 命令添加二进制文件需要 -kb 选项,用 C-u a 则提示输入cvs
   add flags,输入 -kb RET,OK。

6. 查看一些信息

   在一个文件或目录上,或标记了一些文件,按 l 可以在 *cvs-info* 缓冲中看
   到这些文件的 log 信息,就是提交到源码库中的更新日志;按 s 可以看到状态
   信息;按 + 也是状态信息,但是 tag 表为树型结构。

   按 l 查看 log 信息时,*cvs-info* 缓冲的状态为 (Log-View CVS)。此时,有
   很多方便的操作,比如比较两个修订版之间的不同,修改源码库中的 log 信息,
   打开某个文件任意的修订版。比如,在 *cvs* 的某个目录上面按了 l,然后转
   到 *cvs-info* 缓冲中,这里面列出的时该目录中所有文件的 log 信息,此时
   的常用命令如下。

       n, p    移动光标,在一个文件内的不同修订版之间
       N, P    移动光标,在不同的文件之间,M-n, M-p 同样

       m       设置 mark
       d       和设置 mark 的那个修订版进行 diff

       e       修改当前 log,编辑完,C-c C-c 提交

       f, o, RET
               这几个都是打开当前的修订版,稍有区别。用 f 的时候如果提示
               vc-find-version 没有定义,手工加载一下 vc 库
               M-x load-library RET vc RET。

       z       关闭该缓冲

   如果在 *cvs* 的目录里按 s,此时的 *cvs-info* 缓冲为(CVS-Status CVS)状
   态,在这个缓冲中,也可以做类似的一些操作:

       N, P   在文件之间移动, M-n, M-p 同样
       n, p   上一行,下一行

       f, o, RET
              把光标移动到某个 tag 的名字上,则可以直接打开那个 tag 所在
              的修订版

       T, t   把每个文件所列的 tag 表转为树型结构,T 为横向的树,t 为竖向
              的树

   diff 命令产生的 *cvs-diff* 缓冲中也类似,N/P 在文件之间移动,n/p 在不
   同的 diff 之间移动。此外,在任何一行代码的未知按 o 或 RET 可以直接转到
   文件中的实际未知,很方便的。

7. Emacs 的 VC 的方便之处

   在 PCL-CVS 中,几乎可以做任何 CVS 相关的操作。但有时候未免有些麻烦,配
   合 Emacs 的 VC (Version Control) 会方便很多。

   Emacs 的 VC 模式的作者就是著名的 Eric S. Raymond。VC 的功能很强大,而
   且方便灵活。可以使用在三种版本管理系统中:RCS、CVS、SCCS,操作方式一致。
   和 PCL-CVS 不同的是,VC 使用 C-x v 前缀完成大部分功能,不像PCL-CVS 使
   用一个主界面,这使 VC 显得更方便。

   几个主要的命令:

   C-x v v    vc-next-action
              顾名思义,执行下一个动作,下一个动作是什么就执行什么,如果
              是 Unknown 就 cvs add,如果是 Modified 就 commit,如果是
              Up-to-date 就什么都不用做了。最方便的是只需在当前 buffer 中
              执行。

   C-x v m    vc-merge
              将库中别人所做的改动与本地的改动合并,和库中的版本保持一致。

   C-x v a    vc-update-change-log
              更新更改日志文件 ChangeLog。如果源码库或本地拷贝中还没有,
              试一下这个,它会根据 cvs 的提交日志,自动产生 ChangeLog,如
              果已经有了,但已经有一段时间没有更新过,它会自动更新
              ChangeLog 文件到最新的一条记录。

   C-x v ~    vc-version-other-window
              PCL-CVS 也可以方便的查看某个历史版本,不过都需要转到相应的
              控制界面(*cvs* 或 *cvs-info* buffer)中。而 VC 的这个命令可
              以在当前缓冲中用,会提示输入版本号,然后显示在另一个窗口中,
              并保存在当前目录,文件名为 FILENAME.~REV~。

   有时候,用 CVS 管理的东西不需要整体的控制,比如自己的笔记、随笔之类,
   用 Emacs 设置上 bookmark,打开就写点,写完马上就提交,往往不必打开
   PCL-CVS,恰恰 VC 这些灵活的命令非常合适。

   继续了解 VC:

   C-x v =    vc-diff
              比较文件。如果用了前缀参数,会询问和哪个文件的哪个版本比较。

   C-x v u    vc-revert-buffer
              放弃没有提交的改动,恢复原状,也就是你的本地拷贝的版本,并
              不管库中的最新改动。如果想同时和库中别人所做的改动保持一致,
              用 C-u 作为前缀参数。

   C-x v g    vc-annotate
              看看你的每行代码的状态(编辑历史)。每行的颜色用来表示这行代
              码的新旧程度,蓝色的时间最长,红色的最短,其他的居中。默认
              的最长时间为一年,超过一年的都显示为蓝色。用前缀参数可以修
              改所显示的版本和默认最长时间。

              这个缓冲中还有一些有趣的功能,可以直接转到某个修订版。每行
              的最前面为当前行最后一次修改的修订版,在这行上按 J,整个缓
              冲中的内容全都替换为这个修订版;按 N (或 P) 为缓冲中当前的
              后一个(前一个)修订版;按 A 转到当前行上次被修改的版本。N/P
              按修订版历史浏览,A 按当前行修改历史浏览,J 跳转该行所指修
              订版,W 回到该文件的当前修订版。注意,模式行上文件名的后面
              标注了缓冲当前内容的修订版。另外,D 可以比较当前行上的修订
              版和前一修订版的区别,N/P 可以使用前缀参数。

   C-x v d    vc-directory
              打开一个带版本控制功能的 Dired buffer,功能和 pcl-cvs 的
              *cvs* buffer 有些类似。或许对非 CVS 的版本管理比较有用。

8. 相关配置

   由 CVS 管理的模块中都有 "CVS" 目录,打开 cvs-dired-use-hook 时,在
   "CVS" 目录上按 F,直接进入该模块的 *cvs* buffer:
     (setq cvs-dired-use-hook 'always)

   给 cvs-examine 一个方便的绑定:
     (define-key global-map "\C-xve" 'cvs-examine) 绑定到 C-x v e。