用強(qiáng)大且靈活的Mercurial管理源代碼
對(duì)于軟件開(kāi)發(fā)項(xiàng)目,管理源代碼的重要性只略低于編寫(xiě)代碼的重要性。UNIX 和Linux系統(tǒng)提供許多種版本控制系統(tǒng) (VCS) 包,每個(gè)包采用略有不同的方法解決這個(gè)問(wèn)題。本文主要討論 Mercurial 源代碼管理系統(tǒng)(常常簡(jiǎn)稱(chēng)為 hg)。Mercurial 提供一個(gè)強(qiáng)大、現(xiàn)代且輕量的源代碼控制解決方案,讓開(kāi)發(fā)人員可以輕松地更改和調(diào)試軟件項(xiàng)目,同時(shí)維護(hù)一個(gè)穩(wěn)定的中心源代碼存儲(chǔ)庫(kù),所有項(xiàng)目成員都可以依賴這個(gè)存儲(chǔ)庫(kù)。
UNIX 和 Linux 系統(tǒng)上的源代碼管理
識(shí)別和跟蹤多位開(kāi)發(fā)人員所做的更改并把它們合并在最新的單一代碼庫(kù)中,這樣就能夠?qū)崿F(xiàn)協(xié)作性的多開(kāi)發(fā)人員項(xiàng)目。VCS 軟件也稱(chēng)為修訂控制系統(tǒng) (RCS) 或源代碼管理 (SCM) 系統(tǒng),它們讓多個(gè)用戶可以提交對(duì)相同文件或項(xiàng)目的更改,而且保證一個(gè)開(kāi)發(fā)人員的更改不會(huì)意外地覆蓋另一個(gè)開(kāi)發(fā)人員的修改。
Linux® 和 UNIX® 系統(tǒng)上有許多 VCS 軟件,從 RCS 和 Concurrent Versions System (CVS) 等老式系統(tǒng)直到 Arch、Bazaar、Git、Subversion 和 Mercurial 等現(xiàn)代系統(tǒng)。與 Git 一樣,Mercurial 最初是作為替代商業(yè)源代碼管理系統(tǒng) BitKeeper 的開(kāi)放源碼系統(tǒng)出現(xiàn)的,BitKeeper 過(guò)去用于維護(hù)和管理 Linux 內(nèi)核的源代碼。在此之后,Mercurial 發(fā)展成為流行的 VCS 系統(tǒng),許多開(kāi)放源碼和商業(yè)項(xiàng)目都使用它。使用 Mercurial 的項(xiàng)目包括 Mozilla、IcedTea 和 MoinMoin wiki。
VCS 系統(tǒng)一般把每個(gè)可以進(jìn)行更改和跟蹤的源代碼集合稱(chēng)為存儲(chǔ)庫(kù)。開(kāi)發(fā)人員如何與存儲(chǔ)庫(kù)交互是傳統(tǒng) VCS 系統(tǒng)(比如 CVS 和 Subversion,稱(chēng)為集中式 VCS 系統(tǒng))與更靈活的 VCS 系統(tǒng)(比如 Mercurial 和 Git,稱(chēng)為分布式 VCS 系統(tǒng))之間的關(guān)鍵差異。開(kāi)發(fā)人員使用客戶機(jī)/服務(wù)器模型與集中式 VCS 系統(tǒng)交互,對(duì)本地源代碼拷貝的更改只能推回到中心存儲(chǔ)庫(kù)中。開(kāi)發(fā)人員使用對(duì)等模型與分布式 VCS 系統(tǒng)交互,中心存儲(chǔ)庫(kù)的任何拷貝本身都是一個(gè)存儲(chǔ)庫(kù),可以向它們提交更改,其他任何拷貝可以共享其中的更改。分布式 VCS 系統(tǒng)實(shí)際上沒(méi)有中心主存儲(chǔ)庫(kù)的概念,但是差不多總是通過(guò)策略定義一個(gè)主存儲(chǔ)庫(kù),所以有一個(gè)存儲(chǔ)庫(kù)負(fù)責(zé)構(gòu)建、測(cè)試和維護(hù)軟件的主版本。
為什么要使用 Mercurial?
Mercurial 是一個(gè)小型但強(qiáng)大的分布式 VCS 系統(tǒng),它很容易掌握,同時(shí)仍然提供 VCS 高級(jí)用戶可能需要(或希望)使用的高級(jí)命令。由于 Mercurial 的分布式性質(zhì),很容易在本地操作項(xiàng)目、通過(guò)本地提交跟蹤并管理自己的更改以及在需要時(shí)把這些更改推到遠(yuǎn)程存儲(chǔ)庫(kù)。
在現(xiàn)代的分布式 VCS 系統(tǒng)中,最接近于 Mercurial 的 VCS 系統(tǒng)是 Git。Mercurial 和 Git 之間的一些差異如下:
●多種內(nèi)置的撤消操作:Mercurial 的 revert、backout 和 rollback 命令可以簡(jiǎn)便地返回到特定文件的以前版本或以前的已提交更改集。Git 只提供一個(gè)內(nèi)置的 revert 命令,而且語(yǔ)法非常復(fù)雜。
●內(nèi)置的 web 服務(wù)器:Mercurial 提供一個(gè)簡(jiǎn)單的集成的 web 服務(wù)器,很容易快速地駐留存儲(chǔ)庫(kù),讓其他用戶可以從中獲取更改。推操作需要忽略安全性或支持 Secure Sockets Layer (SSL) 的更復(fù)雜的設(shè)置。
●在復(fù)制/移動(dòng)操作期間保存歷史:Mercurial 的 copy 和 move 命令都保存完整的歷史信息,而 Git 在這兩種情況下不保存歷史。
●分支:Mercurial 自動(dòng)地共享所有分支,而 Git 要求每個(gè)存儲(chǔ)庫(kù)設(shè)置自己的分支(在本地創(chuàng)建它們或者把它們映射到遠(yuǎn)程存儲(chǔ)庫(kù)中的特定分支)。
●全局和本地標(biāo)簽:Mercurial 支持在存儲(chǔ)庫(kù)之間共享的全局標(biāo)簽,可以在沒(méi)有分支的情況下方便地共享代碼開(kāi)發(fā)中特定點(diǎn)的相關(guān)信息。
●Windows 平臺(tái)上的原生支持:Mercurial 是用 Python 編寫(xiě)的,而 Microsoft® Windows® 系統(tǒng)支持 Python。因此,可以以 Windows 可執(zhí)行程序的形式使用 Mercurial(見(jiàn) 參考資料)。Windows 上的 Git 比較復(fù)雜,可以選用 msysGit、在 Cygwin 下使用標(biāo)準(zhǔn)的 Git 或者使用基于 web 的托管系統(tǒng)或存儲(chǔ)庫(kù)。
●自動(dòng)的存儲(chǔ)庫(kù)收縮:Git 要求您顯式地對(duì)存儲(chǔ)庫(kù)進(jìn)行收縮和垃圾收集,而 Mercurial 自動(dòng)地執(zhí)行功能相當(dāng)?shù)牟僮?。但是,?duì)于相同的代碼庫(kù),Mercurial 存儲(chǔ)庫(kù)往往比 Git 存儲(chǔ)庫(kù)大。
Mercurial 和 Git 的支持者還希望討論這兩個(gè) VCS 系統(tǒng)的命令集的學(xué)習(xí)難度、優(yōu)點(diǎn)和易用性。由于篇幅的限制,這里不討論這些方面,但是在網(wǎng)上搜索這個(gè)主題會(huì)找到許多有意思的資料。
創(chuàng)建并使用 Mercurial 存儲(chǔ)庫(kù)
Mercurial 提供兩種為項(xiàng)目源代碼創(chuàng)建本地存儲(chǔ)庫(kù)的基本方法:顯式地創(chuàng)建存儲(chǔ)庫(kù)或者克隆現(xiàn)有的遠(yuǎn)程存儲(chǔ)庫(kù):
要想創(chuàng)建本地存儲(chǔ)庫(kù),應(yīng)該使用 hg init [REPO-NAME] 命令。如果在執(zhí)行此命令時(shí)提供存儲(chǔ)庫(kù)名稱(chēng),就會(huì)在指定的位置為此存儲(chǔ)庫(kù)創(chuàng)建目錄。如果不提供存儲(chǔ)庫(kù)名稱(chēng),就會(huì)把當(dāng)前的工作目錄轉(zhuǎn)換為存儲(chǔ)庫(kù)。在為現(xiàn)有的代碼庫(kù)創(chuàng)建 Mercurial 存儲(chǔ)庫(kù)時(shí),后一種做法很方便。
要想克隆現(xiàn)有的存儲(chǔ)庫(kù),應(yīng)該使用 hg clone REPO-NAME [LOCALNAME] 命令。Mercurial 支持使用 Hypertext Transfer Protocol (HTTP) 和 Secure Shell (SSH) 協(xié)議訪問(wèn)遠(yuǎn)程存儲(chǔ)庫(kù)。清單 1 給出一個(gè) hg 命令示例和通過(guò) SSH 克隆存儲(chǔ)庫(kù)時(shí)產(chǎn)生的輸出。
清單 1. 通過(guò) SSH 克隆 Mercurial 存儲(chǔ)庫(kù)
$ hg clone ssh://codeserver//home/wvh/src/pop3check wvh@codeserver's password: destination directory: pop3check requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 12 changes to 12 files updating to branch default 12 files updated, 0 files merged, 0 files removed, 0 files unresolved remote: 1 changesets found
注意:要想使用 HTTP 協(xié)議訪問(wèn) Mercurial 存儲(chǔ)庫(kù),那么必須在此存儲(chǔ)庫(kù)中啟動(dòng) Mercurial 的內(nèi)部 web 服務(wù)器 (hg serve -d),或者使用 Mercurial 的 hgweb.cgi 腳本把 Mercurial 與現(xiàn)有的 web 服務(wù)器(比如 Apache)集成起來(lái)。在通過(guò) HTTP 克隆存儲(chǔ)庫(kù)時(shí),常常要指定本地存儲(chǔ)庫(kù)的名稱(chēng)。
創(chuàng)建或克隆存儲(chǔ)庫(kù)并讓此存儲(chǔ)庫(kù)成為工作目錄之后,就可以開(kāi)始使用其中包含的代碼、添加新文件等等。#p#
在 Mercurial 中獲取幫助
Mercurial 的主要命令是 hg,它支持與其他 VCS 系統(tǒng)相似的一套子命令。執(zhí)行不帶參數(shù)的 hg 命令就可以看到最常用的命令的列表,輸出與 清單 2 相似。
清單 2. Mercurial 提供的基本命令
Mercurial Distributed SCM basic commands: add add the specified files on the next commit annotate show changeset information by line for each file clone make a copy of an existing repository commit commit the specified files or all outstanding changes diff diff repository (or selected files) export dump the header and diffs for one or more changesets forget forget the specified files on the next commit init create a new repository in the given directory log show revision history of entire repository or files merge merge working directory with another revision pull pull changes from the specified source push push changes to the specified destination remove remove the specified files on the next commit serve export the repository via HTTP status show changed files in the working directory summary summarize working directory state update update working directory use "hg help" for the full list of commands or "hg -v" for details
這個(gè)簡(jiǎn)短的列表只顯示基本的 Mercurial 命令。執(zhí)行 hg help 命令可以獲得完整的列表。
提示:執(zhí)行 hg help COMMAND 命令,把 COMMAND 替換為任何有效的 Mercurial 命令,就可以獲得任何 Mercurial 命令的詳細(xì)幫助。
檢查存儲(chǔ)庫(kù)狀態(tài)
簽入 (check in)更改是任何 VCS 系統(tǒng)中最常見(jiàn)的操作??梢允褂?hg status 命令查看對(duì)存儲(chǔ)庫(kù)中的文件所有未完成的更改。例如,在創(chuàng)建新文件或修改現(xiàn)有文件之后會(huì)看到與 清單 3 相似的輸出。
清單 3. Mercurial 的狀態(tài)輸出
$ hg status M Makefile ? hgrc.example
在這里,Makefile 文件是已經(jīng)修改過(guò)的現(xiàn)有文件(由行開(kāi)頭的字母 M 表示),而 hgrc.example 文件是還沒(méi)有跟蹤的新文件(由行開(kāi)頭的問(wèn)號(hào) ? 表示)。
在存儲(chǔ)庫(kù)中添加文件
要想把 hgrc.example 文件添加到存儲(chǔ)庫(kù)跟蹤的文件列表中,應(yīng)該使用 hg add 命令。作為參數(shù)顯式地指定一個(gè)或多個(gè)文件名,就會(huì)把這些文件添加到存儲(chǔ)庫(kù)跟蹤的文件列表中。如果不指定任何文件,就會(huì)把所有新文件添加到存儲(chǔ)庫(kù)中,見(jiàn) 清單 4。
清單 4. 在存儲(chǔ)庫(kù)中添加文件
$ hg add adding hgrc.example
提示:要想自動(dòng)地添加所有新文件并且把已經(jīng)刪除的所有文件標(biāo)為永久刪除,可以使用 Mercurial 的 hg addremove 命令。
檢查存儲(chǔ)庫(kù)的狀態(tài),會(huì)看到已經(jīng)添加了新文件(由行開(kāi)頭的字母 A 表示),見(jiàn) 清單 5。
清單 5. 更改之后的存儲(chǔ)庫(kù)狀態(tài)
$ hg status M Makefile A hgrc.example
提交更改
簽入更改是任何 VCS 系統(tǒng)中最常見(jiàn)的操作。更改代碼并測(cè)試之后,就可以把這些更改提交到本地存儲(chǔ)庫(kù)了。
在第一次提交更改之前
如果這是您的第一個(gè) Mercurial 項(xiàng)目,那么必須提供一些基本信息,讓 Mercurial 能夠識(shí)別提交這些更改的用戶。如果不這么做,在嘗試提交更改時(shí)會(huì)看到包含 abort: no username supplied... 的消息,更改不會(huì)提交。
添加用戶信息的方法是在自己的主目錄中創(chuàng)建文件 .hgrc。這個(gè)文件是您的個(gè)人 Mercurial 配置文件。至少需要在此文件中添加 清單 6所示的基本用戶信息。
清單 6. 用戶的 .hgrc 文件中必需的信息
[ui] username = Firstname Lastname
把 Firstname 和 Lastname 替換為您的名字和姓氏;把 user@domain.tld 替換為您的電子郵件地址;保存修改后的文件。
在 Linux 和 UNIX 系統(tǒng)上的 /etc/mercurial/hgrc 文件以及 Microsoft Windows 系統(tǒng)上 Mercurial 安裝目錄中的 Mercurial.ini 文件中,可以設(shè)置應(yīng)用于所有用戶的默認(rèn) Mercurial 配置值(不應(yīng)該包含針對(duì)特定用戶的信息)。
標(biāo)準(zhǔn)的提交過(guò)程
創(chuàng)建或檢查 ~/.hgrc 文件之后,可以使用 hg commit 命令提交更改,可以指定希望提交的文件;如果不提供參數(shù),就會(huì)提交所有未提交的更改,見(jiàn)以下示例:
$ hg commit Makefile hgrc.example committed changeset 1:3d7faeb12722
如示例輸出所示,Mercurial 把與一次提交相關(guān)聯(lián)的所有更改稱(chēng)為更改集。
當(dāng)提交更改時(shí),Mercurial 啟動(dòng)默認(rèn)編輯器,讓您能夠添加提交消息。要想避免啟動(dòng)默認(rèn)編輯器,可以在命令行上使用 -m "Message.." 選項(xiàng)指定提交消息。要想使用另一種編輯器,可以在 ~/.hgrc 文件的 [ui] 部分中添加一個(gè) editor 條目,在 editor 關(guān)鍵字后面加上希望使用的編輯器的名稱(chēng)和相關(guān)聯(lián)的命令行選項(xiàng)。例如,我通過(guò)添加條目使用非窗口模式的 emacs 作為默認(rèn)編輯器,我的 ~/.hgrc 文件如 清單 7 所示。
清單 7. 用戶的 .hgrc 文件中的進(jìn)一步定制
[ui] username = William von Hagen editor = emacs -nw
提示:要想讓 Mercurial 提供盡可能多的活動(dòng)信息,可以在 Mercurial 配置文件的 [ui] 部分中添加 verbose = True 條目。
把更改推到遠(yuǎn)程存儲(chǔ)庫(kù)
如果使用一個(gè)遠(yuǎn)程存儲(chǔ)庫(kù)的克隆,在把更改提交到本地存儲(chǔ)庫(kù)之后,可能希望把這些更改推到遠(yuǎn)程存儲(chǔ)庫(kù)。這要使用 Mercurial 的 hg push 命令,見(jiàn) 清單 8。
清單 8. 通過(guò) SSH 推更改
$ hg push wvh@codeserver's password: pushing to ssh://codeserver//home/wvh/src/pop3check searching for changes 1 changesets found remote: adding changesets remote: adding manifests remote: adding file changes remote: added 1 changesets with 2 changes to 2 files
從遠(yuǎn)程存儲(chǔ)庫(kù)獲取更改
如果您使用一個(gè)遠(yuǎn)程存儲(chǔ)庫(kù)的克隆,而其他用戶也使用這個(gè)存儲(chǔ)庫(kù),您可能希望獲取他們已經(jīng)完成并推到此存儲(chǔ)庫(kù)的更改。這要使用 Mercurial 的 hg pull 命令,見(jiàn) 清單 9。
清單 9. 通過(guò) SSH 獲取更改
$ hg pull wvh@codeserver's password: pulling from ssh://codeserver//home/wvh/src/pop3check searching for changes adding changesets adding manifests adding file changes added 1 changesets with 0 changes to 0 files (run 'hg update' to get a working copy) remote: 1 changesets found
正如這個(gè)命令的輸出所示,這個(gè)命令只獲取遠(yuǎn)程更改的相關(guān)信息 — 必須運(yùn)行 hg update 命令顯示本地存儲(chǔ)庫(kù)中的相關(guān)更改。這個(gè)命令檢查更新存儲(chǔ)庫(kù)的方式,見(jiàn) 清單 10。
清單 10. 更新自己的存儲(chǔ)庫(kù)以顯示更改
$ hg update 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
在 Mercurial 中撤消更改
Mercurial 提供下面的內(nèi)置命令,它們可以輕松地撤消已提交的更改:
hg backout CHANGESET:撤消特定的更改集并創(chuàng)建撤消此更改集的更改集。除非在執(zhí)行此命令時(shí)指定 --merge 選項(xiàng),否則必須把這個(gè)更改集合并到自己的當(dāng)前修訂中,以便推到遠(yuǎn)程存儲(chǔ)庫(kù)。
hg revert:如果指定一個(gè)或多個(gè)文件的名稱(chēng),就返回到它們的以前版本;如果指定 --all 命令行選項(xiàng),就返回到所有文件的以前版本。
hg rollback:撤消最后一個(gè) Mercurial 事務(wù),通常是 commit、對(duì)遠(yuǎn)程存儲(chǔ)庫(kù)的 pull 或 push。只能撤消一個(gè)事務(wù)。
結(jié)束語(yǔ)
Mercurial 和其他分布式源代碼管理系統(tǒng)是未來(lái)的潮流。Mercurial 是開(kāi)放源碼軟件,有針對(duì) Linux、UNIX、Microsoft Windows 和 Mac OS® X 預(yù)先編譯的 Mercurial 版本。本文主要討論了如何使用 Mercurial 執(zhí)行一些常見(jiàn)的 VCS 任務(wù),說(shuō)明了使用 Mercurial 是多么容易。Mercurial 還提供許多更高級(jí)的命令和配置選項(xiàng),幫助您管理源代碼和定制與 Mercurial 的交互。
【編輯推薦】