Emacs 配合 Subversion 使用

使用 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

现在,用 Emacsworking 目录下面新建一个文件 test1.c ,输入如下内容:

保存,然后按 C-x v v ,VC 会把 test1.c 注册到 svn 仓库里面去,注意看 mode line 上面的 VC Mode指示器显示了“SVN:0”。现在在执行一次 C-x v vEmacs 会弹出一个 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 uEmacs 会显示出 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 之间的区别了 吧?确实是只是修改了 putsprintf 。要看 cool 的 Ediff 的效果,请使用 M-x ediff-revision RET 1 RET 2 RET 。或者,你不习惯看 diff,想看看版本 1 的完整的样子,也没有问题: C-x v ~ 1 RETEmacs 会打开一个 buffer, 并在里面显示版本 1 的内容。现在,让我们来制造一点混乱,再编辑文件,把

改为

保存文件。然后在其他地方在 check out 一个工作副本:

svn co file:///tmp/svnrepo working1

然后进入 working1 目录,修改文件,把

改为

保存,并提交到仓库:

svn ci -m 'change "hello" to "hello world\n"'

好了,现在再回到 Emacstest1.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 的功能:

它包含了用于工作在一个已经 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 配合起来用就非常完美了! ;)