Emacs中的版本控制

原文转载至http://lifegoo.pluskid.org/wiki/EmacsVC.html


Emacs VC 是 Emacs 里面的一个 minor mode 。使用 VC ,你可以很方便地进行版本控制,VC 为你隐藏了几乎所有的版本控制的细节问题,你只要记住一个 VC命令,就能完成几乎所有的版本控制操作,VC 会替你运行正确的命令。

Emacs VC 的基本概念

Emacs VC的接口非常简单,原因在于在某个状态下,只有一件合理的下一步要做的事,规则如下:

  • 如果当前文件不在版本控制之下,下一步要做的合理的事情就是把他注册到仓库,然后为你check out出一个可修改的文件。

  • 如果他已经注册在版本控制之下,并且没有被其他人check out出去,那么就把他check out出来,好让你可以编辑他。

  • 如果你改变了当前文件,那么下一步要做的事情就是提交他。

  • 比较罕见的是,当你工作在比较老的版本控制系统上的时候,如果别人已经check out出去了那个文件,你也许会想steal the lock。

事实上,VC mode只有一个最基本的命令: C-x v v (vc-next-action) 。他的作用就是对当前文件进行下一个合理的VC操作,或者,更确切的说,让当前文件进入下一个正常的版本控制状态。他按照图1中传统的版本控制循环来行事。

                                       	  +----------------+
                                          | steal the lock |
                                          | (if necessary) |
                                       	  +--------+-------+
               	       	       	       	       	   |
          			       	   	   v
                               	                check-out
                         	       +--------->>>>>>------+
				       |       	       	     |
+--------------+  registration	 +-----+------+         +----+-----+
| unregistered | --------------> | registered,|  revert |  locked, |
+--------------+		 |  unlocked  | <------ | editable |
				 +-----+------+         +-----+----+
				       |       	       	      |
				       +-----------<<<<<<-----+
					           check-in
					       	      x
						      |
					 +------------+---------------+
					 |     add change comments    |
					 | (optional, but you should) |
					 +----------------------------+

另外,当你提交的时候,Emacs会弹出一个buffer让你填写日志。类似的,当你工作在比较老的版本控制系统上,准备``steal a lock''的时候,Emacs会弹出一个buffer让你填写说明原因。

VC还有一个恢复操作: C-x v u (vc-revert-buffer) 恢复到上一次check out的状态并解除锁定。

以上是传统的版本控制的流程,VC就是以此为基础设计的,但是现在流行的版本控制系统的工作方式有一点不一样。幸运的是,现在的系统更简单一些,因为没有了为了编辑文件必须获取锁定的必要,VC的其中一个步骤被省略了。如下图所示:

                                      +------------------------+
                                      | normal editor activity |
                                      |  (no locks are used)   |
                                      +------------+-----------+
               	       	       	       	       	   |
          			       	   	   v
                               	               edit document
                         	       +-=-=-=-=->>>>>>-=-=-=-+
				       |       	       	      |
+--------------+  registration	 +-----+------+         +-----+----+
| unregistered | --------------> | registered,|  revert |  locked, |
+--------------+		 |  unlocked  | <------ | editable |
				 +-----+------+         +-----+----+
				       |       	       	      |
				       +-----------<<<<<<-----+
					           commit
					       	      x
						      |
					 +------------+---------------+
					 |     add change comments    |
					 | (optional, but you should) |
					 +----------------------------+

从未修改的状态过渡到已修改的状态在这儿用虚线来表示了,因为这个过程并不需要执行任何VC操作。当你告诉VC你要执行下一步操作的时候,他能够判断出当前文件在上一次check out之后是否已经修改过了,如果修改过,他会弹出一个buffer让你填写日志并提交这个文件。如果这个文件没有被修改过,VC只是显示一条消息告诉你当前buffer是最新的。

编辑 comment buffer

在VC mode里面,三种操作会弹出一个buffer让你输入comment或者notification text:

  • check in

  • steal a lock

  • file registration

这个时候操作会被挂起直到你在comment buffer里面按C-c C-c提交commentbuffer为止。你可以输入comment,也可以去干点其他事情,VC会一直等你。如果你直接把comment buffer关掉了,那么挂起的操作就会被取消。

每次你提交的comment会被保存在一个ring里面。你可以用M-p在这个ring里面往后游历,用M-n往前游历,或者用M-r往后搜索、M-s望前搜索。最常用的命令当然是M-p 。因为我们通常都是连续进行一系列相关的修改,所以编辑上一次提交的comment是非常有用的。

VC 命令总结

这个表是按照VC命令的使用频率排序的,你会发现所有的VC命令都是以C-x v开头的:

VC 命令
快捷键 命令名 动作
C-x v v vc-next-action 让当前文件进入下一个合理的version control状态
C-x v d vc-directory 显示一个目录下所有注册到版本控制下的文件
C-x v = vc-diff 产生一个diff报告
C-x v u vc-revert-buffer 丢弃自从所以此check in以来所做的所有更改
C-x v ~ vc-version-otder-window 取出当前buffer在仓库里的指定版本并在另外一个窗口中显示出来
C-x v l vc-print-log 显示一个文件的历史和日志
C-x v i vc-register 把文件注册到版本控制系统里面去
C-x v h vc-insert-headers 在文件里面插入version control headers
C-x v r vc-retrieve-snapshot check out一个named project快照
C-x v s vc-create-snapshot 创建一个named project快照
C-x v c vc-cancel-version 丢弃一个已经保存的版本
C-x v a vc-update-change-log 更新一个GNU-style的ChangeLog文件

VC Mode Indicator

VC在mode line霸占一块地方用来告诉你当前buffer的version control状态。当你访问一个在version control控制下的文件时,mode line上会显示这个文件所使用的version control系统的名字以及这个文件的版本号:

EmacsVCModeIndicatorDash.png

当两者之间是一个“-”时,说明这个文件还没有check out,是“:”时说明已经被 check out了,版本号是这个文件在你上一次check out的时候的版本号。值得注 意的是现在大多数人都使用并发式的version control系统,并没有checkout文 件并获得锁定的操作,你可以简单的认为“-”表示未修改,而“:”表示已经修改了, 但是还未提交到仓库。

EmacsVCModeIndicatorColon.png

如果你没有看到这些指示器,说明这个文件并没有注册到某个version control系统下面。

EmacsVCModeIndicatorNone.png

各个 VC 命令简介

基本的Emacs VC概念那儿我们已经讲了VC最主要的命令:vc-next-action。这儿我们将按照命令的使用频率的顺序来讲解一下剩下的命令。

同时操作一组文件或者子目录

命令C-x v d (vc-directory)将为你打开一个经过定制了的[[EmacsDired][Diremode]]的buffer,列出目录下的所有注册到版本控制系统里面的文件以及他们的状态。你可以用Dired的那些方便的命令标记一些文件,然后你可以对他们执行vc-next-action或者vc-revert-buffer。如果vc-next-action是提交文件,VC只会让你输入日志一次,但是如果是vc-revert-buffer,对每个文件,VC都会让你确认是否丢弃更改。在这里执行VC命令可以不用加C-x前缀,例如,你可以用v u来执行vc-revert-buffer。

Diff 报告

命令C-x v = (vc-diff)将显示文件的当前工作版本和你上一次提交的时候的版本之间的差异,由此你可以看出,再一次提交会产生什么样的修改。如果你用一个前缀C-u来调用这个命令:C-u C-x v = ,VC会让你填写要比较的文件名以及两个版本号。如果“older revision number”为空(如果你什么都不输入就直接回车就会产生这种效果),他将是你上一次提交的版本;如果“newer revisionnumber”为空,他将是你目前的工作版本。所以输入文件名之后连续两次回车的效果和不用C-u前缀来执行命令的效果是一样的。

如果你传递给C-u C-x v =的文件名事实上是一个目录名,你将会看到目录下面所有注册到版本控制系统下面的文件之间的差异比较报告。

获得旧的版本

你可以用C-x v ~ (vc-version-other-window)来获得文件的任意以前的版本。这个版本将保存到同一个目录下,并在后面加上特定的后缀(事实上,后缀是一个“.”、一个“~”加上版本号再加上一个“~”构成的)。这样,你可以一次获取几个不同的版本,而且这种命名方式也让你可以使用Dired的~命令一次把他们全部标记以便删除。

查看历史

C-x v l (vc-print-log)命令会让VC弹出一个buffer,并在里面显示这个文件的历史以及日志等有用的信息。

注册文件

在非并发式的版本控制系统(如RCS、SCCS)上,vc-next-action 不仅注册一个文件,而且check out一个可编辑版本,而有时候需要仅仅是注册一个文件而不check out,C-x v i (vc-register)就可以完成这个工作。但是在现在流行的并发式的版本控制系统上,两者之间几乎已经没有什么差别了。

插入 Version Control Header

一些版本控制系统鼓励你在文件里面插入一些可以随你check in、check out和revert的时候自动更新的magic string用来产生自动插入的与当前版本号相关的信息:是谁上次修改了他、上一次check in是什么时候等等。

这些header strings很大程度上是和VC mode指示器显示的信息是重复的,剩下的信息你也可以通过C-x v l来得到。所以这个功能看起来好像不是特别有用,但是当你不是在Emacs里面查看文件的时候,这些信息就显得有用了。VC提供插入magic strings的方法,其实他只是插入了对应的占位符,真正信息的填充是在你提交的时候由对应的版本控制来完成的。

VC会试着探测当前文件的注释类型,并以注释的形式插入magic strings,并且VC还会探测你之前是否已经插入了magic string。对于C文件的行为比较特殊,VC并不是把version header放在注释里面,而是产生一个名叫vcid的静态字符串来包含版本信息,这样版本信息就可以被编译到object文件里面,以后你可以用strings工具(如果你使用一个类Unix的环境的话)来查看这个二进制文件是由那个版本的源文件产生的了。2

标记和获取快照

一个工程的快照就是把一个工程里面各个文件的某个版本号联系在一起而得到的一个单元,大多数的版本控制允许你用一个符号名称来标记一个快照,例外的是,SCCS不支持这个特性(VC会为SCCS模拟这个特性),而对于Subversion则根本没有这样的概念,因为在Subversion里面每一个版本号都对应了整个模块的一个快照。

C-x v s (vc-create-snapshot)命令将让你输入一个符号名称,然后VC将当前各个文件对应的版本号关联到那个符号名称上。符号名称可以作为其他需要版本号的VC命令的有效的参数,这在vc-diff的时候是非常有用的。命令C-x v r(vc-retrieve-snapshot)以一个符号名称作为参数,并check out目录下的所有注册到版本控制系统里面的文件对应于符号名称的版本号的版本。

两个命令都有可能失败并返回一个错误。当目录下的某个注册过的文件被别人check out了,vc-create-snapshot命令会失败,in order to avoid making asnapshot that, when retrieved later, won't restore the current statecompletely. 或者是在本地文件更改之后,他也会失败,因为你也许想先提交或者丢弃你的更改。

更新ChangeLog文件

C-x v a (vc-update-change-log)帮助VC与Free Software Foundation的一些工程管理约定协同工作。FSF的工程在每一个目录下面都会有一个ChangeLog文件,包含了目录里面的每一个文件的timestamped修改日志。

Rather than make you enter every change comment twice (!), VC providesa hook that copies recent change comments out of masters beneath thecurrent directory and appends them to a ChangeLog in the approvedformat.

重命名version controled文件

在很多version control系统下面,重命名文件是需要很大技巧的,甚至是非常困难的,vc-rename-file尝试着让你从困境中摆脱出来,他试着把事情做好,并随时报告错误并告诉你他无法完成工作。不过,在Subversion里面这个功能已经变成他的基本功能之一了。

当VC被搞迷糊了的时候

确定一个文件的版本信息的操作有时候是昂贵和缓慢的,特别是在NFS或者其他网络环境里面的时候。VC有两种方式来补偿:

  1. 为每个文件的信息在内存里面建立缓存。

  2. 假设可以通过文件的权限推断出状态。

这有时候会造成问题,比如另外一个用户在VC不知情的情况下手工修改了某个文件的权限,或者是同时有几个VC在对文件进行操作。如果你任何VC被搞迷糊了,就调用vc-clear-contex命令来让VC丢掉所有的缓存。但事实上这样的情况是很罕见的。

其他命令

还有其他没有介绍的和随着新版本的VC而加入的命令,你可以通过 M-x vc-<tab> 来获取一个VC命令的列表,并通过 C-h f vc-command 来得到该命令的文档。

使用 Ediff 进行比较

EdiffEmacs里面非常丰富强大的一个的一个模块,你也许会想用他来比较文件。这儿有三种方法启动Ediff

  1. 用 vc-resolve-conflicts 启动 Ediff 来解决冲突

  2. 用 ediff-revision 启动 Ediff 来比较版本之间的异同

  3. 手工启动 Ediff 来比较两个文件,比如你手动获取的某几个版本的文件

Footnote

1.  这两幅图片的来源是 OReilly.Learning.Gnu.Emacs.3rd.Edition

2. 我在试验Subversion的时候好像这些magic strings并没有得到任何的填充替换,也许这个特性在Subversion里面已经没有了,不过我试验过RCS,是可以正常工作的,基于RCS的CVS系统应该也是有这个特性的吧。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值