git filter-branch の subdirectory-filter を使うのがいいみたいです。履歴も残るのが素晴しいです。
man git-filter-branch
から引用すると
Only look at the history which touches the given subdirectory. The result will contain that directory (and only that) as its project root.
Implies the section called “Remap to ancestor”.
だそうです。
やってみる
まずは元のプロジェクトからサブプロジェクト用の新しいディレクトリに clone します。
$ git clone project-dir new-project-dir
$ cd new-project-dir
filter-branch でサブプロジェクトのディレクトリにある修正だけを有効にします。これで subproject のディレクトリがルートにやってきて、履歴もそこにコミットしたものだけになります。
$ git filter-branch -f --subdirectory-filter path/to/subproject
足りないものがあれば、clone 元からコピーとかでお茶を濁します。履歴が微妙に変なのが気になる人は頑張って rebase してください。まだどこにも push してないので改変しほうだいです。
ここまでで今いるブランチがサブプロジェクトだけのものになりました。
お掃除
origin が不要になので削除します。
$ git remote remove origin
タグも消してしまいます。
$ git tag | xargs git tag -d
ゴミ掃除 (man git-filter-branch
にのってます)。
$ git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
$ git reflog expire --expire=now --all
$ git gc --prune=now
おわり
これでサブプロジェクトが履歴を残したまま分離できました。あとは新しいリポジトリに push して、元のプロジェクトから消しさってしまえばおしまいです。
git すごいですね。