iT邦幫忙

DAY 19
2

EMACS 新思維系列 第 19

[EMACS新思維 第二十二天] 版本管理(Version-Control)

在使用 emacs 處理版本管理時,magit 無疑是很多人的選擇。不過,magit 是一個額外的套件,而且他也僅止於對 git 有良好處理。那面對如其他以 svn / cvs 管理版本的程式員來說無疑不是那麼方便。這裡介紹原生的 vc!(本文部份整理自參考資料)
當你開啟一個有版本管理的檔案時,VC 便會自動啟動。 如果不喜歡這樣,請使用 (setq vc-handled-backends nil) 來取消這個動作。

Emacs-VC 支援:GNU Arch, Bazaar, CVS, Git, Mercurial, Monotone, RCS, SCCS/CSSC, 及 Subversion。每個的操作都是基於 VC 獨特的版本管理模式。

VC 的概念

  1. 如果當前文件不在版本控制之下,下一步要做的合理的事情就是把它註冊到倉庫,然後為你check out出一個可修改的文件。
  2. 如果已經註冊在版本控制之下,並且沒有被其他人check out出去,那麼就把他check out出來,好讓你可以編輯他。
  3. 如果你改變了當前文件,那麼下一步要做的事情就是提交它(commit)。
  4. 比較罕見的是,當你工作在比較老的版本控制系統上的時候,如果別人已經check out出去了那個文件,你也許會想steal the lock。

工作
最重要的指令是 C-x v v (vc-next-action) 。VC 會去檢查目前檔案在版本管理中應該要進行的下一個動作是什麼?然後自動提示你相對應的動作,如彈出一個 buffer 讓你寫註解。底下是 VC 認定的工作邏輯:

在 VC ,下面三種操作會彈出一個 buffer 讓你輸入 comment:

  1. check in (即 commit)
  2. steal a lock
  3. file registration

這個時候對該檔案的操作會強制暫停,直到在 comment buffer 裡面按 C-c C-c 提交 comment buffer 為止。你可以輸入 comment ,或者直到你決定將檔案送入管理內為止,VC 會等待。如果直接關掉comment buffer,那麼操作就會被取消,送入管理庫的動作暫停。

每次你提交的comment會被保存在一個ring裡面。你可以用Mp在這個ring裡面往後遊歷,用Mn往前遊歷,或者用Mr往後搜索、Ms望前搜索。最常用的命令當 然是M-p 。因為我們通常都是連續進行一系列相關的修改,所以編輯上一次提交的comment是非常有用的。

指令列表
C-x v v :vc-next-action 讓文件進入下一個合理的版本管理狀態
C-x v d :vc-directory 顯示目錄下所有在版本管理控制下的檔案
C-x v = :vc-diff 產生一個 diff 報告(似乎透過ediff)
C-x v u :vc-revert-buffer 丟棄所有提交的動態(取消 commit)
C-x v ~ :vc-version-otder-window:取出目前 buffer 對應的檔案,不過是版本管理中提交的最新版(好進行比較)
C-x v l :vc-print-log 顯示歷史與 log
C-x v i :vc-register 把文件註冊到版本管理系統內(next-action 應該會幫你做這個判斷)
C-x v h :vc-insert-headers 在文件內插入 version control headers
C-x v r :vc-retrieve-snapshot 可 check out 一個專案快照(?)
C-x v s :vc-create-snapshot 創建一個快照
C-x v c :vc-cancel-version 丟棄一個已經保存的版本

關於各指令的詳細說明
(注意:底下的部份直接引用參考資料的內容!!)

同時操作一組文件或者子目錄:C-x v d (vc-directory):將以定制過的 dired ,列出目錄下的所有註冊到版本控制系統裡面的文件以及其的狀態。你可以用 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」維持其預設,不輸入 (如果你什麼都不輸入就直接按下 Enter 就會產生這種效果),將是你上一次提交的版本;如果」「newer revision number」維持預設不輸入,他將是你目前的工作版本。所以輸入文件名之後連續兩次按下 Enter 的效果和不用 C-u 前綴來執行命令的效果是一樣的。

如果你傳遞給Cu Cx v =的文件名事實上是一個目錄名,你將會看到目錄下面所有註冊到版本控制系統下面的文件之間的差異比較報告。

**獲得舊的檔案版本:C-x v ~ (vc-version-other-window)**來獲得文件的任意以前的版本。這個版本將保存到同一個目錄下,並在後面加上特定的後綴(事實上,後綴是一個“.”、一個“~”加上版本號再加上一個“~”構成的)。這樣,你可以一次獲取幾個不同的版本,而且這種命名方式也讓你可以使用 Dired 的 ~ 命令一次把他們全部標記以便刪除。

**查看歷史:C-x v l (vc-print-log)**命令會讓 VC 彈出一個 buffer,並在裡面顯示這個文件的歷史以及日誌等有用的信息。

標記和獲取快照:一個工程的快照就是把一個工程裡面各個文件的某個版本號聯繫在一起而得到的一個單元,大多數的版本控制允許你用一個符號名稱來標記一個快照,例外的是, SCCS不支持這個特性(VC會為SCCS模擬這個特性),而對於Subversion則根本沒有這樣的概念,因為在Subversion裡面每一個版本號都對應了整個模塊的一個快照。對應於 git 可以看成是 tag 這個命令?

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 a snapshot that, when retrieved later, won't restore the current state completely. 或者是在本地文件更改之後,他也會失敗,因為你也許想先提交或者丟棄你的更改。

重命名version controled文件:在很多 version control 系統下面,重命名文件是需要很大技巧的,甚至是非常困難的,vc-rename-file 嘗試著讓你從困境中擺脫出來,他試著把事情做好,並隨時報告錯誤並告訴你他無法完成工作。不過,在 Subversion 裡面這個功能已經變成他的基本功能之一了。

當VC被搞迷糊了的時候

確定一個文件的版本信息的操作有時候是昂貴和緩慢的,特別是在NFS或者其他網絡環境裡面的時候。 VC有兩種方式來補償:

  1. 為每個文件的信息在內存裡面建立緩存。
  2. 假設可以通過文件的權限推斷出狀態。

這有時候會造成問題,比如另外一個用戶在VC不知情的情況下手工修改了某個文件的權限,或者是同時有幾個VC在對文件進行操作。如果你任何VC被搞迷糊了, 就調用 vc-clear-contex 命令來讓VC丟掉所有的緩存。但事實上這樣的情況是很罕見的。


上一篇
[EMACS新思維 第二十一天] ibuffer
下一篇
[EMACS新思維 第二十三天] Org-mode (一)
系列文
EMACS 新思維27

1 則留言

我要留言

立即登入留言