はじめに
前回の記事では、SVN運用における課題や、SVNからGit/GitLabへの移行によって期待される改善効果を整理しました。
前回の記事
今回はその続編として、SVNの履歴を保持したままGit/GitLabへ移行する際の事前準備事項や検討事項についてご紹介いたします。
移行にあたっては、既存の運用やSVNとGitの設計上の差異を十分に考慮したうえで、移行や運用設計を行う必要があります。それらのポイントについて記載します。
また、SVNの履歴をGit形式に変換するためのツールとして、git-svnが広く利用されています。
このツールを使用することで、SVNリポジトリのコミット履歴をGitに取り込み、移行後も過去の変更履歴をGitから参照することが可能となります。
本記事では、git-svnを使用します。[1]
1. 移行作業前の準備事項
Gitへの移行を実行する前に、検討すべき事項を整理します。
1.1. SVNリポジトリレイアウトを確認する
移行元のリポジトリレイアウトを把握し、Gitリポジトリの最適な構成を検討します。
- 標準レイアウト(trunk/branches/tags)の場合は、git-svnの追加設定不要で移行可能です(後述の--stdlayoutオプションを使用)。
- カスタムレイアウト(標準レイアウトでない)やモノリポジトリ(複数プロジェクトを1つのSVNリポジトリで管理している)の場合は、パスのマッピング等を決める必要があります。また、SVN上で一体となっていたコード群を単一のGitリポジトリで管理し続けるか、プロジェクトごとに複数のリポジトリへ分割するかを検討します。[2]
履歴やブランチ/タグ欠落のリスクがあります
カスタムレイアウトの場合、git-svnでのパス指定が誤っていると、意図したブランチやタグが正しく変換されず、履歴の欠落や構成の誤りが発生する恐れがあります。
1.2. 移行対象の決定
リポジトリの規模と操作性のバランスを考慮し、移行対象とするブランチ、履歴、ファイルの範囲を明確に定めます。
リポジトリの肥大化によるパフォーマンス低下懸念
不要なデータをGitに取り込むと、リポジトリの肥大化やパフォーマンス低下の原因となります。
そのため、移行対象の適切な選別や、作業前に部分的な検証を行い、容量や履歴の整合性を事前検証することが推奨されます。
-
変更履歴
- 全変更履歴を移行すると、リポジトリサイズが肥大化し操作性の低下を招くおそれがあります。[3]
- 移行対象を直近数年分の履歴に限定することを検討します。
- 古い履歴については、別途アーカイブ用のGitリポジトリに保管することも有効です。
-
ブランチ / タグ
- 更新頻度の低いブランチは、アーカイブ用リポジトリへの移行、あるいは移行対象から除外すること等を検討します。
- リリースタグは将来のバグ対応や保守参照の用途に備え、最新の数件に限定して移行すること等を検討します。
-
バイナリファイル
- バイナリファイルはGitでの直接管理を避け、必要に応じてGit LFS(Large File Storage)[4]の利用を検討します。
- ExcelやWordなど、ファイルロック機能が求められるドキュメント類については、SVNや文書管理システムへの分離が推奨されます。これらのドキュメントを直接移行した場合、編集競合などが生じ管理しづらい場合があります。詳細は「1.3. バイナリファイルの存在有無の確認と管理方針」に記載します。
1.3. バイナリファイルの存在有無の確認と管理方針
大容量のバイナリファイルや、頻繁に更新・参照されるバイナリは、Git本体での直接管理を避け、Git LFSを利用して管理することを検討します。 Git LFSでは、リポジトリ本体にはファイルの実体ではなくポインタ情報のみを保持するため、リポジトリサイズの肥大化を防ぐことができます。
なぜGitはバイナリファイルの管理が苦手か?
Gitはファイルの履歴をスナップショットとして管理し、内部的には差分圧縮(デルタ圧縮)を用いて保存効率を高めています。
しかし、バイナリファイルは内容の差分が検出されにくく、圧縮が効きにくいため、更新のたびに大きな容量が追加で保存される傾向があります。
その結果、頻繁に更新される大容量バイナリをGit本体で管理すると、リポジトリサイズが急速に肥大化し、クローンやフェッチに時間がかかるなど、操作性の低下を招きます。
このようなファイルは、Git LFSなどの外部ストレージ連携を用いて管理することが推奨されます。
1.4. SVNの外部参照/内部参照の扱いの検討
SVNではsvn:externalsプロパティを利用することで別リポジトリや別ディレクトリの内容を参照する仕組みがあり、それぞれ外部参照・内部参照と呼ばれます。ただし、git-svnによるデフォルト移行では、参照元のプロパティ情報だけが取り込まれ、実体ファイル自体は移行されません。
その結果、移行後に中身のないディレクトリが残るリスクがあります。
-
外部参照(他リポジトリを参照)
- 移行後は、依存先を別Gitリポジトリとして独立管理、または同一リポジトリへの統合のいずれかを検討します。
- 参照元・依存先双方の更新フローやバージョン固定有無を事前に整理することが重要です。
-
内部参照(同一リポジトリ内の別ディレクトリ / ファイルを参照)
- svn:externalsを移行前に解除し、実体ファイルを参照先から取得してコミットする、もしくはgit submoduleの活用を検討します。
よくある失敗例
- svn:externalsをそのまま移行し、依存ファイルが抜け落ちてビルドエラー等が発生する可能性があります。
- 特に「バージョンを明示的に固定しているexternals」の場合、移行後も過去の状態を再現する必要があるため、バージョン管理方針の明確化が必須です。
1.5. SVNの空フォルダへの対応
Gitは空のフォルダを管理対象としません。 そのため、移行後も空フォルダを保持する必要がある場合には、以下の方法を検討します。
- git-svnの--preserve-empty-dirsオプションを使用すると、空ディレクトリにプレースホルダファイルが自動生成されます。
- プレースホルダの命名や管理方針を明確にしたい場合は、.gitkeepなどを手動で追加・コミットします。
Gitでは空フォルダは管理対象外であるため、構成上も実際にファイルが存在するディレクトリのみを管理対象とすることが一般的です。 成果物やログ出力先など、特定の用途で空フォルダの保持が求められる場合を除き、必要になった時点で作成する運用が推奨されます。
1.6. コミッター情報のマッピング(Author変換)
git-svnを使用してSVNの履歴をGitに移行する際には、すべてのコミットに「氏名(Author Name)」と「メールアドレス(Author Email)」を付与する必要があります。
SVNではユーザー名のみで履歴が記録されるため、Gitの形式に合わせてユーザー名とGit形式のAuthor情報を対応付けるマッピングファイル(authors.txt)を用意する必要があります。
SVNのユーザー名に特定のドメインを追加することでGitのアカウントとできるような運用であれば、以下のようなスクリプトでSVNのログから抽出したユーザーIDの一覧をもとに作成することもできます。以下は、SVNリポジトリのログからユニークなユーザー名を抽出し、username = Name <email>
形式のauthors.txtを自動生成するPowerShellスクリプトの例です。
スクリプト例
param(
[Parameter(Mandatory=$true)][string]$svnUrl,
[Parameter(Mandatory=$true)][string]$domain,
[string]$output = "authors.txt"
)
svn log $svnUrl --quiet |
Where-Object { $_ -match '^r\d+\s*\|\s*([^|]+)\s*\|' } |
ForEach-Object {
$user = $matches[1].Trim()
"$user = $user <$user@$domain>"
} |
Sort-Object -Unique |
Out-String |
% { [Text.Encoding]::UTF8.GetBytes($_) } |
Set-Content -Path $output -Encoding Byte
上記スクリプトを使用する際は、SVN URLとメールアドレスのドメインを正確に指定する必要があります。また必ずスクリプトの内容と結果を確認し、メールアドレスや氏名の修正を適切に行ってください。
なぜコミッター情報のマッピングが必要か?
Gitでは、すべてのコミットに「Author Name」と「Author Email」が必須です。
そのため、SVNのユーザー名をGit形式のAuthorにマッピングする--authors-fileの事前設定が必要不可欠です。
マッピングが不完全な場合、git-svn実行時のエラーやコミッター情報の不整合等が起こる可能性があります。
2. まとめ
本記事では、主に移行前の準備や検討事項について記載いたしました。
次回は実際にgit-svnを用いた移行作業の詳細について記載いたします。