以下是預計完成的大綱.
1. Mercurial 簡介
2. 一個簡單的操作範例
3. 安裝/設定 (Windows)
4. 安裝/設定 (Linux)
5. 安裝/設定 (Eclipse)
6. 基本操作
7. 進階操作
8. 結論及建議
1. Mercurial 簡介
Mercurial 是一款跨平台的分散式版本管理軟體. 主要由 Python實作, 以及 C 實作的比較工具 diff. 可以用在Windows, Mac OS X, 和大多數 類似 Unix 的平台. Mercurial 的操作, 主要是在命令列下 hg 這個命令完成. hg 是 mercurial (水銀) 的化學符號. 現在也有圖形化介面以及 web 介面.Mercurial 的建立者及主要開發者是 Matt Mackal, 原始碼授權採用 GNU General Public License v2.
參考連結:
Mercurail 的官方網站
http://mercurial.selenic.com/
詳細的Mercurail 命令說明
http://hgbook.red-bean.com/
Mercurial 的中文維基 :
http://zh.wikipedia.org/wiki/Mercurial
2. 一個簡單的操作範例
先舉一個例子, 示範如何建立 Mercurial 資料庫, 複製資料庫, 從資料庫中取出原始碼, 將原始碼更新回資料庫, 輸出差異檔, 整合差異檔到原始的資料庫, 檢視修改的歷史.Mercurial 也提供了圖形化的介面, 但是強烈建議先熟悉命令列的操作. 使用任何的版本控制軟體, 都不能保證版本控制運行正常. 參與開發的成員對版本控制的了解是關鍵. 版本的控制, 需要掌握版本的狀態, 命令列的操作有助於熟悉狀況的了解.
雖然 Mercurial 的安裝還沒有說明, 但是以下的範例提供了所有的實例的細節, 對了解Mercurial 的操作, 已經足夠.
* 注意: 這只是一個例子, 甚至可以說不是典型的. Mercurial 提供了很多不同的方式來完成版本控制的工作. 實務上要用並不需要完全都用到, 要採取那些方式及流程, 應該考量專案的特性, 來找出最適合的組合.
以下列出需要的檔案資料
d:\work\Hello (範例的工作目錄)
d:\work\Hello\Hello.java (範例檔案)
Hello.java 的內容如下:
public class Hello {
public static void main(String[] args) {
System.out.printf("Hello");
}
}
* 注意: 雖然我們用了一個 java 程式當例子, 但是並不會去編譯或執行, 把它當做一般的文字檔案就可以了.
1.建立 Mercurial 檔案
現在我們有一個 Hello 資料夾, 資料夾中有一個檔案, Hello.java在hello 資料夾中, 以命令列執行以下命令:
d:\work\Hello> hg init
執行完後, 資料夾中的的檔案如下
d:\work\Hello (範例的工作目錄)
d:\work\Hello\.hg (Mercurial 的檔案目錄)
d:\work\Hello\Hello.java (範例檔案)
就可以在 hello 資料夾中, 建立 Mercurial 資料夾 .hg, 這部份儘量不要自己去修改, 這邊也不多作介紹.
注意: hg init 並不會自動加入檔案, 只是建立 Mercurial 所需要的檔案架構, 內容是空的.
接著我們用 tip 命令, 看看現在的狀況是怎樣 :
d:\work\Hello> hg tip -vp
changeset: -1:000000000000tag: tip
user:
date: Thu Jan 01 00:00:00 1970 +0000
大概觀察一下, 就可以知道這是一個空空的內容.
2.加入檔案到 Mercurial 中
接下來我們要把原始碼檔案加入 Mercurial首先使用 status 命令, 觀察目前工作目錄, 然後執行 add 命令, 再來看看 status 的結果有什麼不一樣.
d:\work\Hello> hg status
? Hello.java
d:\work\Hello> hg add Hello.java
d:\work\Hello> hg status
A Hello.java
這邊可以看到 status 命令的結果, 檔案名稱前面的符號已經由 ? 變成 A. 表示這個檔案名稱已經被加入 Mercurail, 但是實際上, 檔案的內容要 commit 之後, 才會進到 Mercurial 的資料庫.
d:\work\hello> hg commit
如果只是下這樣的命令, 會跳出一個文字編輯視窗. 告訴你沒有 commit message
d:\work\hello> hg commit -m "Initial version of Hello"
如果操作成功, 這個命令就不顯示訊息. "沒有消息就是好消息"
再來執行 hg tip -vp 這個命令
d:\work\hello> hg tip -vp
changeset: 0:c35c3dfa8d27
tag: tip
user: Nick Lin <lxnick@gmail.com>
date: Mon Feb 04 14:58:48 2013 +0800
files: Hello.java
description:
Initial version of Hello
diff -r 000000000000 -r c35c3dfa8d27 Hello.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Hello.java Mon Feb 04 14:58:48 2013 +0800
@@ -0,0 +1,7 @@
+public class Hello {
+ public static void main(String[] args) {
+ System.out.printf("Hello");
+ }
+}
+
+
到這邊, 我們已經成功的把檔案加入 Mercurial 的資料庫 (嚴格說, 它不算資料庫, 但是這樣講會比教容易了解, 也比較不抝口). 觀察輸出的內容, 除了原始碼的內容, 編輯者的資訊, 更新的註解, 更新的日期, 和前一個版本的差異等等, 都詳細的列出來了.
注意: 在 commit 的命令之後, hg tip -vp 看到的, 才會是更新過的結果. 在這之前, hg tip -vp 看到的仍然會是空空的內容. commit 之後, hg status 也不再顯示 Hello.java 這個檔案.
3.複製 Mercurial 工作區
日常作業中, 最常進行的工作, 就是取出目前的版本, 修改後, 更新成新的版本.以下說明如何從目前的版本, 創建一個複製的版本.以下會以實例, 將 Hello.java 取出, 將輸出改成Hello World!.
d:\work> hg clone Hello HelloWorld
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
Mercurial 把 Hello 的內容, 複製了一份到 HelloWorld. 至於是不是和 copy 的效果一樣 ? 我覺得這個問題不需要, 也不必要去探討.
d:\work> dir
2013/02/04 下午 02:47 <DIR> Hello
2013/02/04 下午 03:13 <DIR> HelloWorld
進到 HelloWorld 的目錄, 觀察 tip -vp 的輸出, 和 Hello 幾乎完全相同.
d:\work\HelloWorld> hg tip -vp
changeset: 0:c35c3dfa8d27
tag: tip
user: Nick Lin <lxnick@gmail.com>
date: Mon Feb 04 14:58:48 2013 +0800
files: Hello.java
description:
Initial version of Hello
diff -r 000000000000 -r c35c3dfa8d27 Hello.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Hello.java Mon Feb 04 14:58:48 2013 +0800
@@ -0,0 +1,7 @@
+public class Hello {
+ public static void main(String[] args) {
+ System.out.printf("Hello");
+ }
+}
+
+
4. 修改原始碼
將以下程式System.out.printf("Hello");
修改為
System.out.printf("HelloWorld");
就不多說了, 請用任意的編輯器完成.
5. 同步修改結果到資料庫
我們先檢查一下, 修改前後的差異. 請下 hg diff 命令來比較目前工作目錄和資料庫中的內容d:\work\HelloWorld> hg diff
diff -r c35c3dfa8d27 Hello.java
--- a/Hello.java Mon Feb 04 14:58:48 2013 +0800
+++ b/Hello.java Mon Feb 04 16:45:33 2013 +0800
@@ -1,6 +1,6 @@
public class Hello {
public static void main(String[] args) {
- System.out.printf("Hello");
+ System.out.printf("HelloWorld");
}
}
比較的結果, 除了檔案的資訊, 差異點的部份, 也可以從列表之中看出來, 新的版本刪除了 - 號的這一行, 新增了 + 號的這一行, 也就是對這一行做了修改.
注意: 務必 commit
d:\work\HelloWorld> hg commit -m "Change to HelloWorld"
此時無聲勝有聲.接下來, 我們看看 Mercurial 所記錄的資料. 請下 hg tip -vp
d:\work\HelloWorld> hg tip -vp
changeset: 1:d55cc16933a2
tag: tip
user: Nick Lin <lxnick@gmail.com>
date: Mon Feb 04 16:59:13 2013 +0800
files: Hello.java
description:
Change to HelloWorld
diff -r c35c3dfa8d27 -r d55cc16933a2 Hello.java
--- a/Hello.java Mon Feb 04 14:58:48 2013 +0800
+++ b/Hello.java Mon Feb 04 16:59:13 2013 +0800
@@ -1,6 +1,6 @@
public class Hello {
public static void main(String[] args) {
- System.out.printf("Hello");
+ System.out.printf("HelloWorld");
}
}
對照之前的輸出結果, changeset 這一欄已經改變, 冒號 (:) 前面的數字已經變成 1, 這是版本號. 冒號 (:) 後面的文數字,是 16 進位的驗證碼, 用來區分不同人, 不同次修改的版本. description 後面的註解, 也已經更新為新的版本. 修正的部份, 也已經以 +/- 號標出來.
6. 輸出/合併修改
如果修改過的結果, 我們還需要傳送整個工作目錄, 那我們在這邊介紹這個軟體, 就真的是浪費時間了. 接下來就來說明如何輸出修改的部份.請執行以下命令d:\work\HelloWorld> hg export 0:c35c3dfa8d27 1:d55cc16933a2 > 20130204-nick.diff 將 hg export 的輸出結果, 重導到 20130204-nick.diff . 這結果其實是一個文字檔, 開啟後內容如下:
# HG changeset patch
# User Nick Lin <lxnick@gmail.com>
# Date 1359961128 -28800
# Node ID c35c3dfa8d27802e160d462588793272baa9cc18
# Parent 0000000000000000000000000000000000000000
Initial version of Hello
diff -r 000000000000 -r c35c3dfa8d27 Hello.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Hello.java Mon Feb 04 14:58:48 2013 +0800
@@ -0,0 +1,7 @@
+public class Hello {
+ public static void main(String[] args) {
+ System.out.printf("Hello");
+ }
+}
+
+
# HG changeset patch
# User Nick Lin <lxnick@gmail.com>
# Date 1359968353 -28800
# Node ID d55cc16933a28296b444136dc6babe29c07fd0cf
# Parent c35c3dfa8d27802e160d462588793272baa9cc18
Change to HelloWorld
diff -r c35c3dfa8d27 -r d55cc16933a2 Hello.java
--- a/Hello.java Mon Feb 04 14:58:48 2013 +0800
+++ b/Hello.java Mon Feb 04 16:59:13 2013 +0800
@@ -1,6 +1,6 @@
public class Hello {
public static void main(String[] args) {
- System.out.printf("Hello");
+ System.out.printf("HelloWorld");
}
}
這部份我們就不多做說明, 並沒有太多不同的地方. 除了命令列的參數的意思是從版本 0 到版本 1 的差異部份, 其他沒有需要說明的部份.
接下來, 我們要把修改的部份整合到原始資料庫.
首先, 把 20130204-nick.diff 這個檔案, copy 到 d:\work\Hello, 然後用 import 來合併
d:\work\Hello> hg import --exact 20130204-nick.diff
applying 20130204-nick.diff
0 files updated, 0 files merged, 1 files removed, 0 files unresolved
接下來, 看看合併的結果
d:\work\Hello> hg tip -vp
changeset: 1:d55cc16933a2
tag: tip
user: Nick Lin <lxnick@gmail.com>
date: Mon Feb 04 16:59:13 2013 +0800
files: Hello.java
description:
Change to HelloWorld
diff -r c35c3dfa8d27 -r d55cc16933a2 Hello.java
--- a/Hello.java Mon Feb 04 14:58:48 2013 +0800
+++ b/Hello.java Mon Feb 04 16:59:13 2013 +0800
@@ -1,6 +1,6 @@
public class Hello {
public static void main(String[] args) {
- System.out.printf("Hello");
+ System.out.printf("HelloWorld");
}
}
用 hg log 看看這個版本的發展過程, 版本發展的歷程, 可以一目了然的列出來.
d:\work\Hello> hg log
changeset: 1:d55cc16933a2
tag: tip
user: Nick Lin <lxnick@gmail.com>
date: Mon Feb 04 16:59:13 2013 +0800
summary: Change to HelloWorld
changeset: 0:c35c3dfa8d27
user: Nick Lin <lxnick@gmail.com>
date: Mon Feb 04 14:58:48 2013 +0800
summary: Initial version of Hello
將資料庫的變更, 同步到目前的工作目錄
d:\work\Hello>hg update tip
0 files updated, 0 files merged, 0 files removed, 0 files unresolved