Git

git で管理してるプロジェクトの中でサブプロジェクトをやってたけど別リポジトリにしたくなったとき

More than 3 years have passed since last update.

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 すごいですね。