使用 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-statu
s
来打开一个 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
配合起来用就非常完美了! ;)