APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

git-svnでSubversionからGit(GitLab)への移行を試してみた

はじめに

こんにちは。CICD施策チームの伊藤です。
今回はgit-svnを利用して、SubversionからGit(GitLab)へのリポジトリ移行を試したので、その方法を記載します。

目次

利用するツール紹介

SubversionとGitについて

SubversionとGitはファイルやソースコードなどのバージョン管理システムです。
いつ、誰が、どのような変更を加えたかを追跡し、必要に応じて過去の状態を復元できます。

Subversion

Subversionは、一つのサーバーでデータを一括管理する「集中型」バージョン管理システムです。

  • 仕組み: サーバー上の「リポジトリ」からファイルを「チェックアウト」して作業し、完了後に「コミット」して変更を反映します。

  • 特徴: コミットした内容は即座に全体へ共有されます。常にリポジトリサーバーと通信する必要があるため、オフライン環境ではコミット(履歴の記録)ができません。

Subversionの構造イメージ

Git

Gitは、各自のローカル環境にリポジトリの完全なコピーを持つ「分散型」バージョン管理システムです。

  • 仕組み: 各ユーザーのPC内に「ローカルリポジトリ」を作成します。作業内容はまずローカルに「コミット」し、準備が整った段階で共有用の「リモートリポジトリ」へ「プッシュ」して公開します。

  • 特徴: 自身のPC内で履歴管理が完結するため、オフラインでもコミットが可能です。

Gitの構造イメージ

Gitリポジトリのホスティングサービスとしては、GitHubやGitLabなどがあります。 
今回の移行検証では、移行先をGitLabのリポジトリとしています。 GitLabに関する詳細は以下、リンクを参照してください。 about.gitlab.com

git-svnコマンド

git-svnは、SubversionとGitを連携させるためのコマンド群です。
既存のSubversionリポジトリから履歴を取り込み、Gitのローカルリポジトリとして操作できるようにします。
あくまで両システムを仲介するツールであり、GitやSubversionのすべての機能が完全に互換しているわけではない点に注意が必要です。

主な用途

  • Subversion環境でのGit操作: 開発現場の制約でSubversionを使わざるを得ない状況でも、ローカル環境ではGitの強力な機能を活用する。
  • Gitへの移行・学習: SubversionからGitへの移行に向けた検証や、既存の履歴を保持したままGitの操作に慣れる。

git-scm.com

環境構成

構成図

事前に準備した環境構成図

環境構築手順

  1. EC2(OS : Amazon Linux 2023、インスタンスタイプ : m5.large)を作成
  2. EC2上に直接Subversionをインストール
  3. SVNサーバ側で扱う移行元リポジトリを作成
  4. EC2上にDockerをインストールし、GitLabをDockerコンテナで起動
  5. EC2上に直接git-svnコマンドをインストール
  6. Subversionリポジトリ内は3つのディレクトリ(trunk, branches, tags)で構成

移行手順の全体像

  1. Subversionリポジトリをgit-svnコマンドでGitローカルリポジトリとしてクローン
  2. Gitローカルリポジトリに対してブランチの命名を変換
  3. Gitローカルリポジトリに対して、ブランチに変換されたSubversionのタグ情報をGitリポジトリのタグに変換
  4. GitLabリモートリポジトリへとプッシュ
    移行イメージ

※項番2、3について、git-svnコマンドを用いてクローンする際に、Subversionリポジトリのブランチ・タグは以下の命名のブランチに変換されるため、Git移行後にブランチ・タグとして認識させるために、命名変更を実施します。

  • ブランチ:origin/<branch name>
  • タグ:refs/remotes/origin/tags/<tag name>

移行できる情報

本手順によって、以下の情報がSubversionからGitLabに移行できることが確認できました。

  • ブランチ/タグ
  • ファイル内容
  • 変更履歴(ユーザー情報も含む)

事前準備

1.ユーザーマッピングファイル(users.txt)の作成

SubversionのユーザとGitLabのユーザを紐づけるためのユーザーマッピングファイルを作成します。
以下のように記載しています。

<SVNユーザ> = <GitLabユーザ名> <GitLabユーザのメールアドレス>

例)

root = Administrator <gitlab_admin_f1e9f1@example.com>
testuser = TestUser <test_user@example.com>

2.GitLabリモートリポジトリの作成

GitLabに移行先となるリポジトリを作成します。

GitLabへログインしたら、画面左上の+マークを押下し、「New project/repository」を選択してください。

GitLabリポジトリ作成(1)

「Create blank project」を押下してください。

GitLabリポジトリ作成(2)

以下の画面に遷移したら、下の3点を入力して「Create project」を押下してください。

  • プロジェクトの名前(例:test2025)

  • プロジェクトを割り当てるグループもしくはユーザ(例:root)

  • 「Initialize repository with a README」のチェックを外す(※今回は移行するためのプロジェクトの為、空で作成。)

Gitリポジトリ作成(3)

3.Gitコマンドとgit-svnコマンドのインストール

EC2上で以下のコマンドを実行して、Gitコマンドとgit-svnコマンドをインストールします。

sudo yum install git -y
git --version

sudo yum install git-svn -y
git svn --version

4.デフォルトブランチをmainブランチとして設定

Subversionのtrunkディレクトリ配下のソースコードを「main」ディレクトリ配下としてクローンさせるため、以下のコマンドを実行します。

git config --global init.defaultBranch main

5.クローン先ディレクトリ作成

SubversionリポジトリをGit形式に変換してクローンするディレクトリを作成します。

mkdir test-project

移行手順

1. Subversionリポジトリをgit-svnコマンドでGitローカルリポジトリとしてクローン

以下のコマンドを実行し、手順2で作ったディレクトリ配下にSubversionリポジトリをクローンします。

git svn clone -s <移行元SVNリポジトリのURL> <事前準備5で作成したディレクトリ> --username <Subversionのユーザ名> --authors-file=<事前準備1で作成したファイル>

例)

git svn clone -s svn://localhost/repos/project test-project --username testuser --authors-file=users.txt

2.ブランチの命名を変換

ブランチの命名変換をスクリプトで実行します。
※移行手順1で作成したGitリポジトリでは、ブランチが「origin/<ブランチ名>」と命名されている状態のため、「origin/」を除いた命名に変換します。

事前準備5で作成したディレクトリ配下に移動します。

cd ./test-project

以下のシェルスクリプト(branch.sh)をtest-project配下に作成します。
シェルスクリプト概要:「git branch -r」コマンドで取得したブランチ名から「origin/」を削除した新しいブランチ名を作成し、そのすべてを新しいブランチ名に切り替えてチェックアウトする

#!/bin/bash

# リモートブランチのリストを取得し、origin/trunk と origin/tags/* を除外
git branch -r | grep 'origin/' | grep -v 'origin/trunk' | grep -v 'origin/tags/' | while read remote_branch; do
    # 'origin/' プレフィックスを削除してブランチ名を取得
    local_branch_name=$(echo "$remote_branch" | sed 's/origin\///')

    # 不要な空白を除去
    local_branch_name=$(echo "$local_branch_name" | tr -d '[:space:]')

    # チェックアウトコマンドを実行
    if [ -n "$local_branch_name" ]; then # 空のブランチ名でないことを確認
        echo "Checking out branch: $local_branch_name from $remote_branch"
        git checkout -b "$local_branch_name" "$remote_branch"
    fi
done

echo "---"
echo "全ての対象リモートブランチの命名変換が完了しました。"

スクリプトを実行します。

./branch.sh

処理が終わったら、移行元Subversionリポジトリにある全ブランチで、以下のような表示が出ているか確認してください。

Switched to a new branch '移行元Subversionリポジトリのブランチ'

5.ブランチに変換されたSubversionのタグ情報をGitリポジトリのタグに変換

ブランチに変換されたSubversionのタグ情報をGitリポジトリのタグに変換するスクリプトを実行します。
※「3.リポジトリをGit形式に変換しながらクローン 」で作成したGitリポジトリでは、タグが「refs/remotes/origin/tags/<tag name>」というブランチに変換されている状態のため、Gitタグに変換します。

シェルスクリプト概要:ブランチに変換されたタグのコミットハッシュを使用してタグを作成する

#!/bin/bash

# コミットメッセージの定義
COMMIT_MESSAGE="Move from svn"

# /origin/tags を含むリモートリファレンスを抽出し、ループ処理
git for-each-ref --format='%(refname)' refs/remotes/origin/tags/ | while read remote_tag_ref; do
    # 'refs/remotes/origin/tags/' プレフィックスを削除してタグ名を取得
    tag_name=$(echo "$remote_tag_ref" | sed 's/refs\/remotes\/origin\/tags\///')

    # 不要な空白を除去
    tag_name=$(echo "$tag_name" | tr -d '[:space:]')

    # タグ名が空でないことを確認
    if [ -n "$tag_name" ]; then
        # コミットハッシュを取得
        commit_hash=$(git rev-parse "$remote_tag_ref")

        # コミットハッシュが取得できたか確認
        if [ -n "$commit_hash" ]; then
            echo "Processing tag: $tag_name (Hash: $commit_hash)"
            # git tag コマンドを実行
            git tag "$tag_name" "$commit_hash" -m "$COMMIT_MESSAGE"
            echo "Tag '$tag_name' created locally."
        else
            echo "Warning: Could not get commit hash for $remote_tag_ref. Skipping."
        fi
    else
        echo "Warning: Empty tag name extracted from $remote_tag_ref. Skipping."
    fi
done

echo "---"
echo "リモートタグのローカルタグへの再作成が完了しました。"

作成したスクリプトを実行します。

./tags.sh

スクリプトの実行が終わったら以下の表示が移行元のタグ分出力されているかを確認してください。

Tag '20250616-01' created locally.

6.GitLabのリモートリポジトリへプッシュ

作成済みのGitLab上のプロジェクトにプッシュをします。

リモートリポジトリの設定をクローン元であるSubversionリポジトリから、移行先GitLabリポジトリに変更します。

git remote add origin <事前準備の手順2で作成した移行先GitLabリポジトリURL>

例)

git remote add origin http://10.0.0.229:8929/migration/test2025.git`

以下のコマンドでリモートリポジトリにプッシュします。

git push origin --all
git push origin --tags

大規模PJでの移行作業における課題について

今回紹介した移行作業を大規模な開発PJで行う際に、以下のような課題があるかと考えられます。

  • 一時的に開発を中断する必要がある
  • 開発チームと移行作業チームで予定の調整が上手くいかない
  • どのような移行戦略をとれば、安全に移行できるか分からない

上記のような課題をどのように克服しながら移行すべきか、以下のウェビナーで解説しています。
登録制になりますが、ソースコード管理システムの移行に課題をお持ちの方はぜひご視聴いただければと思います。

【セッション情報】
1. SDLC事例から学ぶGitLabによる効率化とAI最新情報
2. SVN から GitLab への移行を解説!課題~技術的アプローチ~移行計画策定ヒントまで

dev.networld.co.jp

最後に

今回はSubversionからGitLabへの手動での移行手順を紹介しました。

弊社はGitLabオープンパートナー認定を受けております。
また以下のようにCI/CDの導入を支援するサービスも行っているので、何かご相談したいことがあればお気軽にご連絡ください。

www.ap-com.co.jp