Gitでサブディレクトリを切り出して別リポジトリにする

  • SVNから移行したリポジトリだとモジュールやライブラリ、サブプロジェクトが全て1つのリポジトリに入っていることが多い。
    • Gitだと扱いくいのでリポジトリを分けたいことが結構ある。
    • SVNのTagやBranchは任意のサブディレクトリから作れるので分離するときは注意すること。

サブディレクトリをトップレベルに昇格させてリポジトリを分ける

SVNリポジトリでやってみる

  • SVNをCloneする。
    • TagやBranchもいらないものがたくさんあるので必要な物以外は消したほうが良い。
    • ベタだけどいらないTagとBranchの一覧ファイル(例ではaaa, bbb)を用意して削除してます。
      • 一覧を作っているTag/Branchだけ消したファイルを作って、そのファイルを元にコマンドで削除。
$ git svn clone -s hoge
$ cd hoge
$ 

$ git tag > aaa
$ vi aaa
$ cat aaa | xargs git tag -d

$ git branch > bbb
$ cat bbb | xargs git branch -D

Gitのフィルタコマンドでディレクトリ構成を変更。

$ git filter-branch --subdirectory-filter src/SubProject -- --all

Ref 'refs/tags/subproject-1.2.1' was rewritten
WARNING: You said to rewrite tagged commits, but not the corresponding tag.
WARNING: Perhaps use '--tag-name-filter cat' to rewrite the tag.
WARNING: Ref 'refs/tags/subproject-2.0.0.1' is unchanged
  • なんかTagがらみで怒られるのでオプションを変えてもう一回実行。
$ git filter-branch --subdirectory-filter src/SubProject --prune-empty --tag-name-filter cat -- --all

新しいGitリポジトリを作ってPush

  • 念の為にゴミ掃除してから新しいリモートリポジトリを登録してPushします。
$ git gc --auto
$ git reflog expire --expire=now --all
$ git gc --prune=now
$ git remote add new_origin ssh://git@git.example.com:7999/newproject/subproject.git
$ git push -u new_origin --all && git push --tags
$ git remote remove new_origin

でかいSVNリポジトリでは微妙かも?

  • TagやBranchを削除してgit-gcしてもあまり小さくはなりませんでした。
    • おそらく履歴も削除しないとダメなのかと。ただ、歴史の長い大きなリポジトリだとやってられませんよね・・・。
  • 履歴についてはSVNリポジトリとしてまるっと移行して、切り出したいのは履歴無しで別リポジトリにして始めるというのもアリかと思います。
    • っていうか、そうしてるのもあります。

参考資料

Git - git-filter-branch Documentation

urashita.com

egulog.hatenablog.jp