先日、こちらの記事を書きました。
今回はその続きでSVNリポジトリー構成のバリエーションの話とGitLabなどを中心としたGitリポジトリー管理ツールとのマッピングの話になります。SVNリポジトリー上に実プロジェクトが複数含まれていた場合になります。SVN上での作業というよりも変換直後の複数実プロジェクトが混在する大きなGitリポジトリーをどうGit上で操作し分割していくかになります。
過去のSVNと最近のGitプロジェクト構成
前回の移行はこんなパターンに主に対応。
myproj
├─trunk
├─branches
│ ├─hoge-fix
│ └─foo-func
└─tags
├─RELEASE_1_0
└─RELEASE_2_0
これは、GitLab/GitHubみたいな Group や Subgroup, Organization や Team みたいな概念がある場合、移行先は例えば、
-
https://gitlab.example.com/mygroup/myproj.git
orgit@gitlab.example.com:mygroup/myproj.git
などに単純に移行することになるかと思います。
今回は、次のような形式で、GitLabの場合Group相当の部分にSVNのリポジトリーが存在し、その下にサブディレクトリーとして複数のプロジェクトが存在する場合、
myproj
├─trunk
│ ├─proj-a
│ └─proj-b
├─branches
│ ├─proj-a-hoge-fix
│ └─proj-b-foo-func
└─tags
├─proj-a-RELEASE_1_0
├─proj-a-RELEASE_2_0
└─proj-b-RELEASE_1_0
これを、
-
https://gitlab.example.com/mygroup/proj-a.git
orgit@gitlab.example.com:mygroup/proj-a.git
-
https://gitlab.example.com/mygroup/proj-b.git
orgit@gitlab.example.com:mygroup/proj-b.git
という形でGroup/Project
という形で分けたい場合を想定しています。
作業方法
前回の記事の作業でSVNリポジトリーが次のGitリポジトリーに既に移行できているものとします。
https://gitlab.example.com/mygroup/myproj.git
該当プロジェクトディレクトリーだけを抽出する
myproj
を proj-a
ディレクトリーにcloneし、
$ git clone git@gitlab.example.com:mygroup/myproj.git proj-a
$ cd proj-a/
proj-a
を抽出しそれ以外を削除
$ git filter-branch --prune-empty --subdirectory-filter proj-a master
これで、元の myproj/proj-a/*
の内容が proj-a/*
に抽出され他は消えます。
ブランチの抽出
$ for BRANCH_NAME in $(git branch -r | grep -e 'origin/myproj-a' | sed -e 's:origin/::');do
git checkout "$BRANCH_NAME";
done
$ git checkout master
上記は、proj-a
のブランチ名付与が proj-a-hoge-fix
など proj-a
で始まっているのが条件。
そうでない場合は、何が proj-a
用のSVNブランチであったかを予め確認しリストアップしたブランチ名をテキストに書いておいて、for文で回すなどするのが良いかと思われます。あるいは元のSVNリポジトリーのbranches
を確認しつつ手で、
$ git checkout hoge-fix
$ git checkout foo-func
.
.
するのも数が少なければ良いかと。
幸い、私のSVN環境ではブランチ名前を統一していたので、上記のようにfor文で回せました。
異なるプロジェクトのタグの削除
proj-a
以外の proj-b
, proj-c
, ... のタグが残っているので削除する必要があります。
もっと良い方法があるかもしれませんが、
$ for TAG_NAME in $(git tag -l | grep -v 'proj-b.*'); do
git tag -d "$TAG_NAME";
done
$ for TAG_NAME in $(git tag -l | grep -v 'proj-c.*'); do
git tag -d "$TAG_NAME";
done
.
.
こんな感じで消去。
こちらもブランチ同様に proj-a-RELEASE_1.0
など proj-a
で始まる名前をルールとしてタグ付けしていたので、上記で回せました。ブランチ同様に予めタグ一覧をテキストなどにしてfor文で回したり、GitLabなどをリモートリポジトリーにするなら、タグは残したままpushし、WebGUI上からポチポチと関係ないものを削除するのもアリかもしれません。
リモートへの登録
まあ、ここらへんは普通にリモート先を変更してpushします。
$ git remote rename origin old-origin
$ git remote add origin git@gitlab.example.com:mygroup/proj-a.git
$ git push -u origin --all
$ git push -u origin --tags
繰り返し
以上を proj-b
, proj-c
, proj-d
, ...で繰り返し、
https://gitlab.example.com/myproj/proj-a
https://gitlab.example.com/myproj/proj-b
https://gitlab.example.com/myproj/proj-c
https://gitlab.example.com/myproj/proj-d
などが移行できたら完了。
まとめ
面倒くさいですね。
SVN上でブランチ名、タグ名をある程度ルール化していたから良かったものの、そうでなかったらもっと手間がかかるはず。