Windows環境でのSubversionからGitへのリポジトリ移行作業についてまとめました。
似たようなことは SubversionからGitへの移行でチーム影響を最小限にする - Qiita にも書いていますが、作業中心に短く書いています。
作業はWindowsマシン上で行い、Gitリポジトリは作業を行うローカル環境のほかにリモートリポジトリを作成するものとします。
必要なツール
以下をあらかじめインストールしておきます。
Gitリポジトリを作成する
移行先となるGitリポジトリを作成します。
チームで共用するリモートGitリポジトリ(GithubやGitlab上など)はあらかじめ作成しておきます。
ローカルGitリポジトリを作成
まずは移行作業を行うためのローカルリポジトリを作成します。
git svn init
でSubversionリポジトリを登録し、Subversionリポジトリの変更はgit svn fetch
で取り込みます。
git svn init \
-T <trunkのURL>
-b <branchesのURL>
-t <tagsのURL>
--username=<ユーザー名> #認証がある場合はパスワードの入力をします
# ※svn init --prefix=svn/ でSubversionのブランチのみにprefixをつけておくこともできます
git svn fetch
# 以下、Subversionでの変更履歴の取り込み。大きなリポジトリだとかなり時間がかかる
上記コマンドを実行すると、ローカルリポジトリにSubversionのブランチとタグが取り込まれています。Subversion上のブランチとタグはremotes/以下に登録されています。
git branch -a
* master
remotes/20141204_xxx-1.0.0
... その他ブランチ一覧。省略
remotes/tags/20141126-xxx-1.0.0
... その他タグ一覧。省略
remotes/trunk
.git/config
を見ると、svn-remote
という項目にSubversionリポジトリ独自のrefspecが設定されています。
[svn-remote "svn"]
url = http://svn-server/xxx/my-project
fetch = src/xxx/trunk:refs/remotes/trunk
branches = src/xxx/branches/*:refs/remotes/*
tags = src/xxx/tags/*:refs/remotes/tags/*
Gitのブランチ・タグを作成
git svn fetch
でSubversionのブランチやタグのrefがremotes/以下に入ります。
ここからGitのローカルブランチ・タグを作成して、Gitのリモートリポジトリにpushします。
ブランチを作成
タグはtags/xxx
のような名前でrefが作成される。ブランチのみGitのブランチを作成する。
git branch -r | egrep --text --invert-match "tags|trunk" | xargs -iBRANCH_NAME git branch BRANCH_NAME BRANCH_NAME
タグを作成
git branch -r | egrep --text "tags/" | cut -d / -f2 | xargs -iVAR git tag VAR tags/VAR
Gitのリモートリポジトリへpush
あらかじめGitのリモートリポジトリを用意しておきます。
このリポジトリにはhttp://my-repo/my-project.git
でアクセスできるものとします。
git remote add origin http://my-repo/my-project.git
git push origin --all # すべてのブランチをpush
git push origin --tags # すべてのタグをpush
SubversionとGitのリポジトリを並行して利用する場合の差分適用
複数の案件を並行で開発しているチームでSubversionからGitへ移行する場合、どうしても開発をストップできない状況になることもあるかと思います。
その場合は、SubversionリポジトリとGitリポジトリを併用する移行期間を設けて、両者の差分を適用しながら開発を進めることができます。
以下の例ではSubversionリポジトリ、Gitリポジトリ両者にfeature-a
という共通のブランチが作成されているものとします。
Subversionリポジトリの差分をGitリポジトリに取り込む
Subversionリポジトリのfeature-a
ブランチでも開発は続いており、この差分をGitリポジトリへ取りこみたい場合は以下のような作業を行います。
# Subversion側の修正をすべて取得
git svn fetch
# リモートのGitリポジトリでの修正を取得
git fetch origin feature-a
# Gitリポジトリのブランチをcheckout
git checkout feature-a
# Gitのfeature-aへSubversionのfeature-aをマージ
git merge remotes/feature-a
# Gitのリモートリポジトリへpush
git push origin feature-a
上記の作業を行うことで、Subversionリポジトリでの差分もGitリポジトリへ取り込むことができます。
Gitリポジトリの差分をSubversionリポジトリに取り込む
逆に、Gitリポジトリでの差分をSubversionリポジトリへ取り込む場合は以下のようにします。
# Subversionリポジトリでの変更を取り込みます
# ローカルブランチfeature-aに反映させます
git svn fetch
git checkout feature-a
git merge remotes/feature-a
# ローカルGitリポジトリでリモートGitリポジトリの変更を取り込みます
git fetch origin
git checkout feature-a
# Gitリポジトリでの差分を --squash で1つにまとめてマージコミットを作成します
git merge origin/feature-a --squash
git commit
# dcommitでSubversionリポジトリへ反映させます
git svn dcommit
# dcommitしたらGitのリモートリポジトリにもマージコミット分をpushします
git push origin feature-a