ksaitoの日記

日々試したことの覚え書き

Subversionの複数リポジトリをまとめる

Subversionリポジトリ複数に分割して運用しているケースは多いと思います。
その理由は、管理する側の都合ということが多いようです。
環境構築やバックアップといったことを考えると1つのリポジトリ複数プロジェクトを収容する方がメリットがあると考えます。
既に複数に分割しているリポジトリを1つにまとめるのは意外と簡単です。

準備

手順を説明するために2つのリポジトリを準備します。
.repo1には、project1を作り、.repo2には、project2とproject3を作ります。
実際の操作をする際には、統合前のリポジトリのフルダンプを取りましょう。

$ svnadmin create .repo1
$ svnadmin create .repo2
$ mkdir -p t/trunk t/tags t/branches
$ svn import t file://`pwd`/.repo1/project1 -m "init"
追加しています              t/trunk
追加しています              t/branches
追加しています              t/tags

リビジョン 1 をコミットしました。
$ svn import t file://`pwd`/.repo2/project2 -m "init"
追加しています              t/trunk
追加しています              t/branches
追加しています              t/tags

リビジョン 1 をコミットしました。
$ svn import t file://`pwd`/.repo2/project3 -m "added project3"
追加しています              t/trunk
追加しています              t/branches
追加しています              t/tags

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

リポジトリを統合する

.repo1と.repo2をダンプし、.repo3にインポートします。
古いリポジトリからsvnadmin dumpした結果を新しいリポジトリにsvnadmin loadするだけです。

$ svnadmin dump .repo1 | svnadmin load .repo3
* リビジョン 0 をダンプしました。
* リビジョン 1 をダンプしました。
<<< オリジナルのリビジョン 1 に基づき、新しいトランザクションを開始しました
     * パスを追加しています : project1 ... 完了しました。
     * パスを追加しています : project1/branches ... 完了しました。
     * パスを追加しています : project1/tags ... 完了しました。
     * パスを追加しています : project1/trunk ... 完了しました。

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

$ svnadmin dump .repo2 | svnadmin load .repo3
* リビジョン 0 をダンプしました。
* リビジョン 1 をダンプしました。
* リビジョン 2 をダンプしました。
<<< オリジナルのリビジョン 1 に基づき、新しいトランザクションを開始しました
     * パスを追加しています : project2 ... 完了しました。
     * パスを追加しています : project2/branches ... 完了しました。
     * パスを追加しています : project2/tags ... 完了しました。
     * パスを追加しています : project2/trunk ... 完了しました。

------- 新しいリビジョン 2 を (オリジナルのリビジョン 1 からロードして) コミットしました >>>

<<< オリジナルのリビジョン 2 に基づき、新しいトランザクションを開始しました
     * パスを追加しています : project3 ... 完了しました。
     * パスを追加しています : project3/branches ... 完了しました。
     * パスを追加しています : project3/tags ... 完了しました。
     * パスを追加しています : project3/trunk ... 完了しました。

------- 新しいリビジョン 3 を (オリジナルのリビジョン 2 からロードして) コミットしました >>>

$ 

結果を確認する

統合された結果を確認します。
ログももれなく統合されています。

$ svn ls file://`pwd`/.repo3
project1/
project2/
project3/
$ svn log file://`pwd`/.repo3
------------------------------------------------------------------------
r3 | | 2010-02-11 09:34:50 +0900 (木, 11  2 2010) | 1 line

added project3
------------------------------------------------------------------------
r2 | | 2010-02-11 09:34:29 +0900 (木, 11  2 2010) | 1 line

init
------------------------------------------------------------------------
r1 | | 2010-02-11 09:23:13 +0900 (木, 11  2 2010) | 1 line

init
------------------------------------------------------------------------
$

同じ名前のプロジェクトの統合

同じ名前のプロジェクトを統合する場合には、割り切りが必要です。
例えば、.repo1のproject1は、名前をprojectXに変更しても前のリビジョンに同じ名前があるのでインポートできません。

$ svn mv file://`pwd`/.repo1/project1 file://`pwd`/.repo1/projectX -m "rename"

リビジョン 2 をコミットしました。
$ svnadmin dump .repo1 | svnadmin load .repo3* リビジョン 0 をダンプしました。
* リビジョン 1 をダンプしました。
* リビジョン 2 をダンプしました。
<<< オリジナルのリビジョン 1 に基づき、新しいトランザクションを開始しました
svnadmin: ファイルが既に存在します: ファイルシステム '.repo3/db', トランザクション 3-4, パス 'project1'
     * パスを追加しています : project1 ...$ svn ls file://`pwd`/.repo3
project1/
project2/
project3/
$ 

過去のコミットログやproject1から名前を変更したなど履歴は、あきらめる必要があります。(たぶん)
svnadmin dumpにリビジョンを指定して統合します。

$ svnadmin dump -r HEAD:HEAD .repo1 | svnadmin load .repo3
* リビジョン 2 をダンプしました。
<<< オリジナルのリビジョン 2 に基づき、新しいトランザクションを開始しました
     * パスを追加しています : projectX ... 完了しました。
     * パスを追加しています : projectX/trunk ... 完了しました。
     * パスを追加しています : projectX/branches ... 完了しました。
     * パスを追加しています : projectX/tags ... 完了しました。

------- 新しいリビジョン 4 を (オリジナルのリビジョン 2 からロードして) コミットしました >>>

$ svn ls file://`pwd`/.repo3
project1/
project2/
project3/
projectX/
$

この方法を使えば、既存のリポジトリレイアウトを新しいレイアウトに合うように修正して、持ってくることができます。
履歴を残したいプロジェクトを一番最初にインポートすることが大切です。