Subversion+svkでらくらく分散リポジトリ

第4回SVKでリポジトリ管理実践編

前回の記事ではSVKの基本的な操作方法を説明しました。最終回の今回はSubversionのリポジトリと連携しながら、SVKの使い方を説明します。

リモートのSubversionのリポジトリとして、本連載第2回目で説明した方法でSubversionのリポジトリを作成します。リポジトリを作成しただけではファイルがない状態です。今回はテスト用のデータを用意しました。ファイルをダウンロードしてc:\tmp\ディレクトリに展開してください。展開後、次のコマンドを実行して、Subversionのプロジェクトにインポートします。

C:\> cd c:\tmp\gihyo
C:\tmp\gihyo> svn import http://localhost/svn/MyProject/ -m "test project"
認証領域: <http://localhost:80> trac
'Administrator' のパスワード: 
認証領域: <http://localhost:80> trac
ユーザ名: user1
'admin' のパスワード: ********
追加しています              trunk
[中略]
追加しています              tags

リビジョン 1 をコミットしました。

C:\tmp\gihyo>

次にtrunkからテスト用のブランチを作成します。

C:\tmp\gihyo> svn copy http://localhost/svn/MyProject/trunk http://localhost/svn/MyProject/branches/remote

これまでの操作で図1のようなディレクトリ構造になります。

図1 テスト用Subversionリポジトリのディレクトリ構造
図1 テスト用Subversionリポジトリのディレクトリ構造

以上で準備ができました。これから、SVKのリモートリポジトリ管理を行ないます。今回のミッションでは、trunkでファイルの変更を行い、コミットします。次に、trunkの変更分をbranchにマージします。

リモートリポジトリをミラーリング

SVKで管理するときは、まず、リモートリポジトリをSVKのローカルにミラーリングします。次のようなコマンドの書式になります。

svk mirror SubversionのリポジトリのURL SVKのリポジトリ名

それでは、ミラーリングを行ないます。次のコマンドを実行してください。

C:\tmp\>svk mirror http://localhost/svn/MyProject //mirror
Authentication realm: <http://localhost:80> trac
Password for 'admin':
Mirror initialized.  Run svk sync //mirror/trunk to start mirroring.

C:\tmp>

ここでは、//mirrorと言うパスにミラーリングしています。ここでは、SVKのファイルの保管場所のことをローカルリポジトリ、SVKリポジトリ内の各ディレクトリのことをパスと呼びます。複数のリモートリポジトリを管理する場合は、⁠//mirror/プロジェクト名」のようにパスを指定すると分りやすいです。

次のコマンドを実行することで、ミラーリングしているパスを確認できます。

C:\tmp>svk mirror --list
Path             Source
=====================================================
//mirror         http://localhost/svn/MyProject

C:\tmp>

ミラーしたものは、現在のリモートリポジトリのスナップショットです。チームで開発している場合、あなたの作業中にもファイルを更新しているかもしれません。定期的に、ミラーリングしているローカルリポジトリをリモートリポジトリと同期する必要があります。次のコマンドを実行して、リモートリポジトリと同期してください。

C:\tmp>svk sync //mirror
Syncing http://localhost/svn/MyProject
Retrieving log information from 2 to 2

C:\tmp>

複数のリモートリポジトリを管理している場合は、次のコマンドを実行することで、すべてのリモートリポジトリと同期できます。

svk sync --all

ローカルブランチがあなたの作業領域

SVKではミラーリングしているパスに対して直接編集しません。代わりに、ローカルリポジトリ内でローカルのブランチを作成します。次のコマンドを実行して、//mirror/trunkを//workにコピー(ブランチを作成)します。ミラーしているパスをチェックアウトした場合、コミットするとSubversionのリポジトリに直接コミットされてしまいます。ミラーしているパスをチェックアウトしないように注意してください。

C:\tmp>svk copy //mirror/trunk //work
Waiting for editor...
Committed revision 10.
C:\tmp>

作業用ブランチが作成できたので、作業コピーとしてファイルをチェックアウトします。次のコマンドを実行して、//workをc:\tmp\MyProjectにチェックアウトします。

C:\tmp>svk checkout //work MyProject
Syncing //work(/work) in C:\tmp\MyProject to 10.
A   MyProject\README.txt
[中略]
A   MyProject\index.html

C:\tmp>

現在のリポジトリの構造は図2のようになっています。

図2 作業リポジトリのトポロジー図
図2 作業リポジトリのトポロジー図

作業領域を最新に

「svk sync」を実行することでミラーリングしているパスをリモートリポジトリと同期して最新の状態にできます。しかし、ローカルブランチは古いリビジョンの状態のままです。ローカルブランチを最新の状態にするためには、マージ(smerge)します。

まず、Subversionのクライアントを使ってリポジトリに変更を加えておきます。今回はテスト用に、trunkのdocsディレクトリを削除して、次のようにREADME.txtの最初の方に文書を追加しています。

===========
SVK Sample
===========
 
This is modified for SVK test.
This line is the remote modification for conflict test.

This is SVK Sample Project.

最初に次のコマンドを実行して、ミラーリングしているリポジトリを最新の状態にします。

C:\tmp\MyProject>svk sync --all

次に、ローカルブランチ//workにマージします。実際にローカルブランチにマージする前に、次のコマンドを実行してコンフリクトがないかチェックします。

C:\tmp\MyProject>svk smerge -C //mirror/trunk //work
Auto-merging (7, 11) /mirror/trunk to /work (base /mirror/trunk:7).
U   README.txt
D   docs
New merge ticket: 3d528234-c470-8440-b20e-186cbe60fd7c:/trunk:3

C:\tmp\MyProject>

この結果から、衝突はなく問題なくマージできることがわかります。次のコマンドを実行して、マージします。⁠-l」オプションを指定すると、コミットメッセージとして、Subversionのコミットログが自動的に使用されます。これは、ローカルで起きた変更とリモートで起きた変更が区別できるので、履歴を確認するときに役立ちます。

C:\tmp\MyProject>svk smerge -l //mirror/trunk //work
Auto-merging (7, 11) /mirror/trunk to /work (base /mirror/trunk:7).
Waiting for editor...
U   README.txt
D   docs
New merge ticket: 3d528234-c470-8440-b20e-186cbe60fd7c:/trunk:3
Committed revision 12.

C:\tmp\MyProject>

これで、SVKのローカルブランチが最新の状態になりました。最後に、次のコマンドを実行して作業コピーを最新の状態にします。

C:\tmp\MyProject>svk update
Syncing //work(/work) in C:\tmp\MyProject to 12.
U   README.txt
D   docs

C:\tmp\MyProject>

衝突が起きたとき

開発中にはなるべく衝突が起きないようにすることが大事ですが、実験的な修正を行なっているときやブランチでの作業中は衝突が発生することがあります。次に、衝突が起きたときの動作を見てみましょう。

衝突が起きるように、まず、Subversionのリポジトリのファイルhttp://localhost/svn/MyProject/trunk/README.txtを次のように編集してコミットします。

===========
SVK Sample
===========

This is modified for SVK test.
This line is modified for conflict test. (remote)

This is SVK Sample Project.

ローカルの作業コピーC:\tmp\MyProject\README.txtを次のように変更します。

===========
SVK Sample
===========

This is modified for SVK test.
This line is modified for conflict test.(local)
 
This is SVK Sample Project.

C:\tmp\MyProject\README.txtを変更後、次のコマンドを実行して、ローカルリポジトリにコミットします。

C:\tmp\MyProject>svk commit README.txt
Waiting for editor...
Committed revision 13.

C:\tmp\MyProject>

これで衝突が起きる状態になりました。まず、リモートリポジトリとミラーリングしているリポジトリを同期します。

C:\tmp\MyProject>svk sync //mirror/trunk
Syncing http://localhost/svn/MyProject/trunk
Retrieving log information from 4 to 4
Committed revision 14 from revision 4.
C:\tmp\MyProject>

同期が完了後、マージを行ないます。

C:\tmp\MyProject>svk smerge -l //mirror/trunk //work

コマンドを実行すると、コミットログの入力を求められるので、最初の行に「conflict test」と入力します。しばらくすると、次のメッセージが表示されます。

Conflict found in README.txt:
e)dit, d)iff, m)erge, s)kip, t)heirs, y)ours, h)elp? [e] 

「d」を入力すると、次のような差分が表示されます。

--- README.txt (YOURS)
+++ README.txt (MERGED)
@@ -3,7 +3,13 @@
 =======

 This is modified for SVK test.
+>>>> YOUR VERSION README.txt (/work) 119781301192861
 This line is modified for conflict test.(local)
+==== ORIGINAL VERSION README.txt 119781301192861
+This line is the remote modification for conflict test.
+==== THEIR VERSION README.txt (/mirror/trunk) 119781301192861
+This line is modified for conflict test. (remote)
+<<<< 119781301192861

 Python program for RSS aggregation and filtering.

自分の変更を適用する場合は「y」,リモートリポジトリの変更を適用する場合は「t」を入力します。マージする場合は「m」を入力します。今回はファイルを直接編集するので、⁠e」を入力します。notepadが立ち上がり、ファイルの内容が次のように表示されます。 表示の形式は本連載1回目の衝突ファイルの表示形式と同じです。

===========
SVK Sample
===========

This is modified for SVK test.
>>>> YOUR VERSION README.txt (/work) 119781301192861
This line is modified for conflict test.(local)
==== ORIGINAL VERSION README.txt 119781301192861
+This line is the remote modification for conflict test.
==== THEIR VERSION README.txt (/mirror/trunk) 119781301192861
This line is modified for conflict test. (remote)
<<<< 119781301192861
 
This is SVK Sample Project.

このファイルを編集して保存、終了すると次のメッセージが表示されます。⁠a」を入力するとこの変更が適応されます。⁠e」を押すと再編集できます。⁠d」を押すとオリジナルとの差分を表示します。⁠s」を押すと変更が破棄されます。ここでは「a」を押して変更をコミットします。

修正が終わると、ローカルリポジトリのローカルブランチに変更がコミットされます。マージが終るわと、次のコマンドを実行してSVKの作業コピーに更新を反映します。

C:\>tmp>MyProject> svk update

マージは複雑なように見えます。ブランチへのマージではSubversionの場合、前回マージしたときのリビジョンと現在マージしようとしているリビジョンの番号を調べてマージする必要があります。SVKではマージするリビジョンはすべて自動で処理されるため、Subversionより簡単に処理できます。マージ時には、二つのリビジョン間の単純な差分ではなく、そのリビジョン間で起きたすべての差分情報をもとにマージするため、Subversionのマージより安全です。

変更をリポートリポジトリに反映

現状ではローカルリポジトリに加えた変更は、Subversionのリモートリポジトリには反映されていません。次にリモートリポジトリに変更分をコミットする作業を行います。次のコマンドを実行して、リモートリポジトリに反映します。smergeコマンドは、マージ先がミラーリングしているパスの場合、マージ処理を行なった後にSubversionのリポジトリにコミットします。その後、Subversionのリモートリポジトリとミラーリングしているパスを同期します。

C:\tmp\MyProject>svk smerge -C //work //mirror/trunk
Auto-merging (0, 22) /work to /mirror/trunk (base /mirror/trunk:21).
Checking locally against mirror source http://localhost/svn/MyProject/trunk.
Empty merge.

C:\tmp\MyProject>svk smerge -l //work //mirror/trunk
Auto-merging (0, 22) /work to /mirror/trunk (base /mirror/trunk:21).
Waiting for editor...
Merging back to mirror source http://localhost/svn/MyProject/trunk.
Empty merge.

C:\tmp\MyProject>

図3は、TracのリポジトリブラウザからSubversionのリポジトリを参照しています。マージした結果が反映されているのが分かるでしょうか?

図3 Tracのリポジトリブラウザから変更を確認
図3 Tracのリポジトリブラウザから変更を確認

//mirror/branches/remoteに変更分をマージするには、次のコマンドを実行します。これは、ブランチが作成されたときのリビジョン情報とworkに対して加えられた変更を元に、必要な変更分だけをマージします。

C:\tmp\MyProject>svk smerge -l //work //mirror/branches/remote

Tracのリポジトリブラウザでbranchの内容を確認してみてください。branchにも変更が適用されているのが分ると思います。SVKを使って定期的にtrunkからbranchにマージを行なうことで、trunkの変更をbranchに簡単に適用できます。Subversionでこの作業を行ったことがある人は分かると思いますが、これはとても煩雑で難しい作業です。SVKでは、この作業の大半を自動で行なうので、かなりの作業が軽減されます。

おわりに

2回にわたってSVKの機能について説明してきました。SVKには本連載では説明できなかった多くの機能があります。まだ一部のギークにしか認知されていない、コマンドラインのクライアントしかないなど、一般の開発者には敷居が高いかもしれません。しかし、Subversionのマージ機能に不満を持っている方や、trunkとbranch両方のツリーで作業をされている方は一度検討してみるといいかもしれません。

おすすめ記事

記事・ニュース一覧