git-svn(git svn サブコマンド)を使って Subversion リポジトリを Git リポジトリに変換します。以前変換したことはあるんですが、その時に変換方法について書いてはいませんでした。

まず git-svn を何とかしてインストールします。Debian/Ubuntu あたりなら apt install git-svn。バージョン 2.34.1 (svn 1.14.1) が入りました。

次に Subversion のユーザー名を Git のユーザー名とメールアドレスにマップするファイルを書きます。gitusers.txt という名前にします。

umezawa = UMEZAWA Takeshi <umezawa@abc.example.com>
tgreen = Thomas Green <tgreen@def.example.org>

実際に変換します。

PROJNAME=hogehoge
git svn clone --stdlayout --authors-file gitusers.txt --no-metadata SVN_REPOSITORY_URL ${PROJNAME} 2>&1 | tee ${PROJNAME}.log
cd ${PROJNAME}
git log # ザックリ確認

--stdlayout が Subversion 側のディレクトリ構成(trunk, branches, tags の位置)が標準的であることを示します。--authors-file がユーザー名のマッピングを行うファイルの指定です。これだけだと変換後の Git リポジトリのコミットログに、トラブルシューティングに有用なメタデータ(Subversion でのリビジョンとか)が含まれるのですが、Subversion リポジトリを git コマンドで扱うのではなく Git リポジトリに変換するつもりなら不要なので --no-metadata を指定します。あとは git log などとして軽く確認します。

必要ならタグやブランチを Git の形式に変換します。標準的なディレクトリ構成を持つ Subversion のリポジトリを git svn で clone した状態では、タグは origin/tags/タグ名、ブランチは origin/branches/ブランチ名 というブランチ名、つまり Subversion の慣習に従ったリモートブランチとして扱われます(タグもブランチになります)。

git branch -r | less
for B in $(git branch -r | awk -F/ '$1~/origin/ && $2=="branches" {print $3}'); do git branch ${B} origin/tags/${B}; done
for T in $(git branch -r | awk -F/ '$1~/origin/ && $2=="tags" {print $3}'); do git tag ${T} origin/tags/${T}; done

ところで、Subversion の仕様として、タグやブランチを作る操作自体もコミット扱いになります。Git に変換してもそれは維持されています。そのため、タグだったものは元のリビジョンから枝分かれして空のコミットを1つだけ持つブランチに変換されています。そのため、上記の方法では、元のブランチ上にタグが現れません。もしそれが問題であるなら、1つ前に戻った場所をタグにする必要があります。

for T in $(git branch -r | awk -F/ '$1~/origin/ && $2=="tags" {print $3}'); do git tag ${T} origin/tags/${T}^; done

空コミットが入るのはブランチの場合も同様ですが、ブランチの根元から空コミットを除去するのは面倒ですし、タグの場合ほどは問題ではないでしょうから、紹介するのはやめておきます。(単にやり方を考えてないだけ)

これで変換は完了なので、Git のリモートリポジトリに push します。

git remote add origin GIT_REPOSITORY_URL
git push origin master SOME_TAGS SOME_BRANCHES # 必要ならタグやブランチも push

それでは、快適な Git ライフを。

Trackback

no comment untill now

Add your comment now