27 March 2015

SubversionをGitHubにクローン(コピー)する方法

Subversionリポジトリを、GitHubリポジトリに履歴構造を維持したまま一括コピーし、さらにSubversion側でアップデートが発生した場合差分をGitHubにコピーする方法。

20150327-svn2git-image.png

SSHで公開鍵認証をするための事前準備

SSH接続(Gitコマンドのsvn+ssh接続)の設定例

~/.ssh/config
Host example.com
 User USERNAME
 HostName example.com
 IdentityFile ~/.key/id_rsa
 IdentitiesOnly yes

GitHubのSSH接続の設定例

~/.ssh/config
Host github.com
 Hostname github.com
 User git
 IdentityFile ~/.key/id_rsa_github
 IdentitiesOnly yes

空のGitHubリポジトリにSubversionリポジトリをまるごとコピー

ローカル・ディスクにSubversionリポジトリをダウンロードする

$ git svn clone -s [--authors-file=TEMPLATEFILE] svn+ssh://USERNAME@example.com/svn/REPO_NAME  [LOCAL_REPO_DIR]

もしくは

$ git svn init -s svn+ssh://USERNAME@example.com/svn/REPO_NAME LOCAL_REPO_DIR
$ cd LOCAL_REPO_DIR
$ git svn fetch [--authors-file=../TEMPLATEFILE]

■ Subversionリポジトリ内のtrunk, branches, tagsディレクトリ名の指定。

オプション指定内容
--trunk=DIRNAME/trunkディレクトリ名を指定本流データが入っている唯一のディレクトリ
--branches=DIRNAME/branchサブディレクトリを束ねた親ディレクトリ名を指定このディレクトリ下に複数のブランチを作成できる
--tags=DIRNAME/tagサブディレクトリを束ねた親ディレクトリ名を指定このディレクトリ下に複数の完成パッケージデータを作成できる
--stdlayout | -s標準のディレクトリ名を採用ディレクトリ名はそれぞれtrunk, branches, tags

20150327-svn-dir.png

branchもtagも使わず、Subversionリポジトリのルートディレクトリに直接データ(ソースコード等)を置いている場合は、 --trunk=/ と指定する。

■ コミットしたユーザ名を書き換える

SubversionとGitでユーザ名が違う場合、 --authors-file=TEMPLATEFILE で書き換えを行える。

オプション指定内容
--authors-file=TEMPLATEFILE次に示すテンプレートファイルを指定する毎回同じ内容なら、~/.gitconfigに指定することも可能

名前書き換えのテンプレートファイルの例(無記名のSubversionコミットが存在した場合、「Author: (no author) not defined in author_conv.txt file」というエラーが出るのを阻止するため、(no author) という項目を設けておくこと)

~/.gitsvn_authors_convert.txt
Subversionでの名前1 = Gitでの名前1 <メールアドレス1@example.com>
Subversionでの名前2 = Gitでの名前2 <メールアドレス2@example.com>
...
(no author) = 無記名の時に採用する名前 <メールアドレスn@example.com>

Git設定ファイルにあらかじめ設定する例

~/.gitconfig
[svn]
    authorsfile = /home/USER/.gitsvn_authors_convert.txt

■ ルートディレクトリにtrunk/対象のソースコードを直接格納している場合のダウンロード例

$ git svn clone --trunk=/ svn+ssh://USERNAME@example.com/svn/REPO_NAME

ローカル・ディスクのリポジトリデータをGitHubにアップロードする

$ cd LOCAL_REPO_DIR
$ git branch -m master main    ← メインブランチ名を「master」から「main」に書き換える
$ git remote add origin git@github.com:USERNAME/REPONAME.git
$ git push origin --all
$ git push origin --tags

既にコピー済みのGitHubリポジトリに、Subversion側のアップデート分を追加

GitHubへ新規コピーの時と同じ手順で行えば、Git側で必要なアップデート分のみが適用される。

$ git svn clone -s svn+ssh://USERNAME@example.com/svn/REPO_NAME  LOCAL_REPO_DIR
$ cd LOCAL_REPO_DIR
$ git remote add origin https://github.com/USER/REPO_NAME
$ git push origin --all
$ git push origin --tags

(補足情報)リポジトリからSubversionへのリモート設定を削除する

git-svnでSubversionからクローン コピーしてきたリポジトリには、Subversionへのリモート設定が残存している。これは、 git remote rm [name] では削除できず、リモート ブランチも dir branch -r -d [name] だけでは消去できない。

まず、リモート設定とブランチを一覧表示する

$ git branch  -a
* master
  remotes/svn/trunk       ← これを削除したい
$ git remote -v
       ← Gitのリモートとしては何も表示されない

(1)configファイルからgit-svn設定を削除(またはコメントアウト)

(下記の例ではコメントアウトしている)

[repo dir]/.git/configソースコード
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
#[svn-remote "svn"]
#	url = svn+ssh://USERNAME@example.com/svn/REPO_NAME
#	fetch = :refs/remotes/svn/trunk
#	branches = branches/*:refs/remotes/svn/*
#	tags = tags/*:refs/remotes/svn/tags/*
#[svn]
#	authorsfile = /home/user/.gitsvn_authors_convert.txt

(2)リモートのブランチを削除する

$ git branch -r -d svn/trunk
Deleted remote-tracking branch svn/trunk (was 392aecc).

tagsを使っている場合は、そちらも一括して削除

$ for BRANCH in $(git branch -r|grep tags); do git branch -r -d $BRANCH; done

そして、ガベージコレクト

$ git gc
Counting objects: 21, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (14/14), done.
Writing objects: 100% (21/21), done.
Total 21 (delta 8), reused 0 (delta 0)

(3)git-svn設定ディレクトリを一括削除

$ rm -r [repo dir]/.svn/