Git
Subversion

Windowマシンで行う git-svnでのSubversionからGitへの移行方法

More than 3 years have passed since last update.

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