📑

svn repositoryをgitに変換する全体手順

2024/12/28に公開

昨今のソフトウェア開発においてはgitを使うことが大半だと思います。
またCICDなどのソフトウェアエコシステムもgitを利用することが前提です。

svnを利用していると、こうした世の中の新しい技術を採用できず、歯痒い気持ちを感じる場面があります。

その課題意識をもとにしてsvnからgitへの移行を推進されている人も多いと思います。

本記事においてはそうした方の手助けとなるように、かつてsvnからgitに移行した際の全体の手順とポイントをまとめています。

同じような取り組みをされている方の手助けになると幸いです。

参考とした記事

今回の取り組みでは以下の記事を参考にさせていただきました。先人の皆さんありがとうございました。

Git-svnでSubversionからGitに移行しよう。 #Git - Qiita

仕事で使ってる巨大SVNレポジトリをGithubに移管するためにやったことまとめ · DQNEO日記

SVNからGitへ移行/リポジトリの分割/リポジトリの階層構造変更 まとめ #Subversion - Qiita

Subversion リポジトリをインポートする - GitHub Docs

今回の内容で移行できるもの

svnはVCSとして現在も現役で使われています。長年運用されているsvnには先人のcommitやtagなど貴重な開発データが蓄積されています。
今回の記事の内容を実行すると、以下のデータはgitに引き継ぐことができます。(※svnに詳しくないのですが、おそらく開発に必要なデータはほぼ移行できると思っています)

  • commit 履歴
  • committerの名前
  • tags
  • branch

また、移行後のgit commit履歴の中にsvnのrevision番号も記録されるため、gitへの移行後に「svnのrevision番号で検索したい」というニーズにも対応できます。

利用するコマンド

git には svnをgitに変換するコマンドが用意されています。

Git - git-svn Documentation

このコマンドを実行することで、先ほど述べたsvnのデータも自動的にgitの形式として移行できます(git の開発者に大感謝)

移行手順

それでは移行手順全体を説明します。今回はsvnの構造は以下の通りです。

  • 保存先のURL
  • ディレクトリ構成
    • trunk
    • branches
    • tags

svnからgitへの変換に利用するコマンドは以下の通りです。

svnの容量によっては変換に時間がかかるため余裕のある時に実行してください。

git svn clone --trunk=/trunk --branches=branches --tags=tags --localtime --authors-file authors.txt https://example.com/svn [target-folder]

--trunk --branches --tags

svnのtrunk,branches,tagsを指定します。

optionなしでも実行できますが、option指定しない場合には、元のsvnのtrunk,branches,tagsの名称が、そのままtrunk,branches,tagsであるとして実行します。

環境によっては、trunkがTrunkなど大文字始まりの場合もあると思います。こうした場合にはoptionを用いて明示的に対応づける必要があります。
例えば以下のような形式です

--trunk=/Trunk --branches=Branches --tags=Tags

それぞれの環境に応じて調整してください。

また、もしtrunk,branches,tagsなどを用いていない場合には、こちらのオプションは無しで実行できます。

--localtime

コミット日時を現地時間に設定します。
このオプションがない場合、コミット日時がUTCになります。

日本国内であれば、元のsvnのコミット日時もJSTで記録されている場合が多いと思いますので、このoptionを指定します。

--authors-file

svnのcommitterをgitのcommitter形式に変換します。

指定したファイルの中に、svnのcommitterに対応するgit commiterが存在しない場合、git svnの変換コマンドが停止します。

authorsファイルの作成方法は後述します。

[target-folder]

svnから変換したgitを配置するフォルダを指定します。ローカルの作業フォルダを指定します。

authorsファイルの作成

svnのcommitterをgitの形式に変換するために以下のコマンドを実行します。

※こちらのコマンドは、committerの銭湯文字が t の場合にその文字をそのまま削除してしまいます。おそらくtab変換がうまくいっていないので、その点だけ注意お願いします。

svn log [SVN_PATH] -q | grep -e '^r' | awk 'BEGIN { FS = "|" } ; { print $2" = "$2 }' | sed 's/^[ \t]*//' | sort | uniq  > authors.txt

※こちらのコマンドはいずれかの記事を参照したのですが参照した記事を控えるのを忘れており、リンクを貼れていません。もし気づいた方がいればコメント等もらえると助かります。

[SVN_PATH] には、変換対象のsvnのURLを指定します。
localにcloneしてある場合には、そのプロジェクト直下でも実行できます。

ここで指定する時に、SVN_PATH/trunkのように特定のフォルダのみを指定すると、そこにcommitのあるcommitterしか抽出されず、git svnによる変換コマンドがエラーで停止します(git svnはbranchesやtagsも変換対象としているため)

なので、trunk等を含むルート[SVN_PATH]直下をターゲットとして実行してください。

実行結果のファイルは以下の通りとなっています。変換後のgitでのcommiter名を、=より右に記載します。
※committerが記録されていない場合には、(no author) と記録されます。

(no author)  =  (no author)
svn_user1  =  svn_user1
svn_user2  =  svn_user2

gitのcommiter名を記載

(no author)  =  no author <no-authors@example.com> 
svn_user1  =  svn_user1 <svn_user1@example.com>
svn_user2  =  svn_user2 <svn_user2@example.com>

ここまで完了すると、svnがgitに変換されています!

branchesやgitのbranchとして、またtagsはtagsとして記録されています。branchesの量が多い場合には、不要であるならば削除など適宜調整をしてください。

残りは、作成されたgit repositoryにてremoteを指定。remoteにpushすればひとまず移行は完了です!

変換後のgitにて、svnのcommitを検索

変換後のgitにてsvnのcommitを検索するには以下のコマンドを使います。

git log --all --grep="svn.*\@"

また、svnの特定のrevision番号を指定したい場合には、以下を実行します。

git log --all --grep="svn.*\@[revision-number] "

[revision-number]の後ろのspaceは空けるようにしてください。

spaceを省くと、@[revision-number].*に合致するrevisionが検索されます。例えば、@3.*とすると、30,31,32...もヒットします。

参考)既存のrepositoryに統合

ここの手順はWebにもいくつか記事がありますので、適宜参照してください。こちらは参考までに掲載しておきます。

svnからgitに変換したあとは、通常のgit repositoryとして取り扱えます。
作成したgit repositoryを既存のgit repositoryに統合したい場合には、以下の手順を実行します。

(import先となるgitの存在するディレクトリに移動し)、 import先となるgit repositoryのremoteに、統合元のgit repositoryを指定して登録

git remote add source-git-repo /path/to/your/target/git/repo

import先となるgit repoにて以下のコマンドを実行

git merge --allow-unrelated-histories -X subtree=target/path source-git-repo/main
  • subtree
    • import元のgit repoを配置したいディレクトリを指定
  • source-git-repo/main
    • 登録したremoteレポジトリ/対象のブランチ名 を指定
    • 登録したsource-git-reporemoteの、main ブランチをimportする

Discussion