使用 Emacs 的 VC minor mode
Emacs 有一个 VC minor mode ,让各种版本控制的操作可以在 Emacs 里面非常 方便地进行。最新的 cvs 版的 Emacs 已经支持 Subversion 了。
比较详细的文档请看基本的Emacs VC操作。下面我们来看一个简单的例子,来简 要的说明最常用的几个功能。首先创建一个Subversion仓库:
svnadmin create /tmp/svnrepo
创建一个空工程,导入仓库:
mkdir test svn import test file:///tmp/svnrepo -m "initial import test"
然后check out出自己的一个工作目录:
svn co file:///tmp/svnrepo working
现在,用 Emacs 在 working
目录下面新建一个文件 test1.c
,输入如下内容:
保存,然后按 C-x v v
,VC 会把 test1.c
注册到 svn 仓库里面去,注意看
mode line 上面的 VC Mode指示器显示了“SVN:0”。现在在执行一次 C-x v v
,Emacs 会弹出一个 buffer 让你输入提交日志,现在输入
first commit test1
并按 C-c C-c
,于是 Emacs 用你输入的日志把 test1.c
提交到 svn 仓库中。
注意现在 mode line 上显示了“SVN-0”,说明这个文件自从你上次提交之后都没
有变过。现在修改源文件,把
改为
保存,看到 mode line 上面的 VC Mode指示器的改变了吗?变成了“SVN:0”,说
明文件自从上一次 commit 之后有所改变。那么现在让我们来看看究竟改变了什
么,按 C-x v =
,Emacs 会弹出一个 buffer 显示你自从上次
commit 之后所做的改变。你也可以用 M-x ediff-revision
来使用Ediff来获得
更灵活方便的交互式的比较和更cool的显示。假如你觉得这样的改变不好,那么
丢弃自从上一次提交以来的所有更改吧: C-x v u
,Emacs 会显示出
C-x v =
显示的那个画面,告诉你你所做的更改,并问你是否确认
要丢弃所做的更改。好吧,我们先不丢弃更改,选择否。然后,在用 C-x v d
来
打开 working
目录,看看当前的状态,哦,显示:
-rw-r--r-- (modified) 2006-05-01 20:09 test1.c
就是说 test1.c
更改了,那我们就把他提交到仓库吧,让光标到 test1.c
上或者给
他做上 mark ,并按 v v
,OK!Emacs 又弹出了那个输入日志的 buffer ,现在输入
change puts to printf
并按 C-c C-c
提交。现在变成了:
-rw-r--r-- 2006-05-01 20:09 test1.c
按 q
退出 Dired ,再回到了 test1.c
的 buffer。再注意到 mode line 的改变。
现在,假如我忘记了刚才做了什么更改,想看看日志,没问题: C-x v l
,现在
Emacs 弹出了日志 buffer:
Working file: test1.c ------------------------------------------------------------------------ r2 | kid | 2006-05-01 20:19:37 +0800 (Mon, 01 May 2006) | 2 lines change puts to printf ------------------------------------------------------------------------ r1 | kid | 2006-05-01 20:08:10 +0800 (Mon, 01 May 2006) | 2 lines first commit test1 ------------------------------------------------------------------------
哦,现在知道了,是把 puts
变成了 printf
。仅仅是这样的改变吗?这只是日
志提供的信息,万一我写日志的时候漏掉了某些内容呢?我还是来看看这两个版
本的区别吧:C-u C-x v = RET RET RET
这么多 RET
是因为都是
Emacs 所提供的默认选项,OK!现在看到了版本号 1 和版本号 2 之间的区别了
吧?确实是只是修改了 puts
到 printf
。要看 cool 的 Ediff 的效果,请使用
M-x ediff-revision RET 1 RET 2 RET
。或者,你不习惯看 diff,想看看版本
1 的完整的样子,也没有问题: C-x v ~ 1 RET
,Emacs 会打开一个 buffer,
并在里面显示版本 1 的内容。现在,让我们来制造一点混乱,再编辑文件,把
改为
保存文件。然后在其他地方在 check out 一个工作副本:
svn co file:///tmp/svnrepo working1
然后进入 working1 目录,修改文件,把
改为
保存,并提交到仓库:
svn ci -m 'change "hello" to "hello world\n"'
好了,现在再回到 Emacs 的 test1.c
,现在用 C-x v v
提交。Emacs 弹出
buffer 让你输入日志,记住你以前输入的日志都被 Emacs 暂时记住了,按一下
M-p
,上一次输入的日志会出现:
change puts to printf
现在,改成
change "hello" to "hello world!"
并按 C-c C-c
提交,不出所料,这次就没有那么顺利了,提交不成功,Emacs 显示
了错误的原因:
svn: Commit failed (details follow): svn: Out of date: 'test1.c' in transaction '3-1' Sending test1.c
原来是“别人”提交了 test1.c
的新版本呀。那我们更新一下吧! M-x
vc-update
呵呵!看到 Emacs 说什么?*vc* buffer 里面显示:
C test1.c Updated to revision 3.
但是 minibuffer 里面有一句:
vc-svn-merge-news: Couldn't analyze svn update result
呵呵!我目前用的 Emacs 22.0.50.1 出现这样的错误,不知道是bug还是没有实
现的功能,因为 Subversion 是新出现的东西,所以 VC 的 Subversion 接口也
是还在开发中的。不过,现在查看 working
目录,发现已经多了几个文件:
test1.c.mine
之类的,这正是 Subversion 出现冲突的迹象,重新打开一下
test1.c
,发现里面有 Subversion 插入的冲突标记:
发现原来忘记假换行符了,于是,可以手工修改,或者用 M-x
vc-resolve-conflicts
来调用 Ediff 来华丽地修改。之后怎么办呢?我还不知
道 VC 目前支持不支持这个东西,也不知道 vc-resolve-conflicts
会不会自动
去除conflict 标记,现在先让我们手工运行一下 Subversion 的命令吧: M-!
svn resolved test1.c
去除 conflict 标记。
好啦!到目前为止,我们的例子结束!因为我已经把我目前知道的大部分功能都 展示了一下,希望 VC 的 Subversion 接口将来做得更好!:)
使用 psvn.el
psvn — Subversion interface for Emacs
psvn.el 是 Emacs 的一个 Subversion 接口。他提供类似于 pcl-cvs 的功能:
- 显示Subversion工作拷贝的状态
- 显示不同的版本之间的差别
- 显示版本日志
- 编辑文件属性
- 提交工作拷贝的更改
它包含了用于工作在一个已经 check out 出来的 Subversion 的工作拷贝上的各 种功能。如果你缺少了某种功能或者是发现了一个 Bug,请发送 Email 到 stefan@xsteve.at 。一个详细的 ChangeLog 可以在 svn ViewCvs server 获得。 最新版的 psvn 可以从 http://www.xsteve.at/prg/emacs/psvn.el 获得,或者通 过 Subversion 仓库得到:
svn co http://svn.collab.net/repos/svn/trunk/contrib/client-side/psvn psvn
psvn 使用简介
下载 psvn.el ,并添加其路径你的 Emacs 的 LoadPath 里面。然后在自己的 .emacs 里面加入:
用 M-x svn-status
来打开一个 svn-status
的 buffer,这个 buffer 处于
svn-status mode
中,可用的命令如下:
g - svn-status-update: run 'svn status -v' M-s - svn-status-update: run 'svn status -v' C-u g - svn-status-update: run 'svn status -vu' = - svn-status-show-svn-diff run 'svn diff' l - svn-status-show-svn-log run 'svn log' i - svn-status-info run 'svn info' r - svn-status-revert run 'svn revert' X v - svn-status-resolved run 'svn resolved' U - svn-status-update-cmd run 'svn update' M-u - svn-status-update-cmd run 'svn update' c - svn-status-commit run 'svn commit' a - svn-status-add-file run 'svn add --non-recursive' A - svn-status-add-file-recursively run 'svn add' + - svn-status-make-directory run 'svn mkdir' R - svn-status-mv run 'svn mv' D - svn-status-rm run 'svn rm' M-c - svn-status-cleanup run 'svn cleanup' b - svn-status-blame run 'svn blame' X e - svn-status-export run 'svn export' RET - svn-status-find-file-or-examine-directory ^ - svn-status-examine-parent ~ - svn-status-get-specific-revision E - svn-status-ediff-with-revision X X - svn-status-resolve-conflicts s - svn-status-show-process-buffer e - svn-status-toggle-edit-cmd-flag ? - svn-status-toggle-hide-unknown _ - svn-status-toggle-hide-unmodified m - svn-status-set-user-mark u - svn-status-unset-user-mark $ - svn-status-toggle-elide w - svn-status-copy-filename-as-kill DEL - svn-status-unset-user-mark-backwards * ! - svn-status-unset-all-usermarks * ? - svn-status-mark-unknown * A - svn-status-mark-added * M - svn-status-mark-modified * D - svn-status-mark-deleted * * - svn-status-mark-changed . - svn-status-goto-root-or-return f - svn-status-find-file o - svn-status-find-file-other-window v - svn-status-view-file-other-window I - svn-status-parse-info V - svn-status-svnversion P l - svn-status-property-list P s - svn-status-property-set P d - svn-status-property-delete P e - svn-status-property-edit-one-entry P i - svn-status-property-ignore-file P I - svn-status-property-ignore-file-extension P C-i - svn-status-property-edit-svn-ignore P k - svn-status-property-set-keyword-list P y - svn-status-property-set-eol-style P x - svn-status-property-set-executable h - svn-status-use-history q - svn-status-bury-buffer C-x C-j - svn-status-dired-jump
它和 EmacsVC 配合起来用就非常完美了! ;)