Gitリポジトリの一部を別リポジトリに分離する(リポジトリの分割)
前提条件
- 基本的に仕事ではgit-flowを採用している。
- 今回は、まだ作り始めて間もないのでmasterはREADME.mdと.gitignoreしかない。
- developは、最小限の動くソースとドキュメントが入っている。
- 書きかけのfeatureブランチがあり、新しいドキュメント用リポジトリに移った後で書き続けたい。
どうやって実現する?
- 調べるとまず
git filter-branch --subdirectory-filter sub_dir_name HEAD
というやり方が引っかかる。- これをやってみると、sub_dir_nameで指定したディレクトリがトップレベルになってしまうのでダメ。(ディレクトリの階層構造は維持したまま分割したい)
git filter-branch --tree-filter 'command'
というやり方でリポジトリを改変できるらしい。- これはスゴイ。必要なディレクトリだけ残して消してみよう。
分割を実施
projects/ $ cd original_repo original_repo/ (develop) $ git checkout master Switched to branch 'master' Your branch is up-to-date with 'origin/master'. original_repo/ (master) $ ls README.md original_repo/ (master) $ git remote add new_origin ssh://git@git.example.com:7999/hogehoge/foo_doc original_repo/ (master) $ git push new_origin Counting objects: 4, done. Delta compression using up to 8 threads. Compressing objects: 100% (4/4), done. Writing objects: 100% (4/4), 718 bytes | 0 bytes/s, done. Total 4 (delta 0), reused 3 (delta 0) To ssh://git@git.example.com:7999/hogehoge/foo_doc * [new branch] master -> master original_repo/ (master) $ git remote remove new_origin
- developは、ソースは消してドキュメントは改変せずに残しておきたい。
original_repo/ (master) $ git checkout develop Switched to branch 'develop' Your branch is up-to-date with 'origin/develop'. original_repo/ (develop) $ cd .. projects/ $ git clone process_service foo_repo_develop Cloning into 'foo_repo_develop'... done. projects/ $ cd foo_repo_develop foo_repo_develop/ (develop) $ ls README.md docs src foo_repo_develop/ (develop) $ git filter-branch --tree-filter 'rm -rf src' --prune-empty Rewrite cf15eff0fdf6e3a8622a93956f624ab152a4ac8d (28/28) Ref 'refs/heads/develop' was rewritten foo_repo_develop/ (develop) $ git gc Counting objects: 515, done. Delta compression using up to 8 threads. Compressing objects: 100% (337/337), done. Writing objects: 100% (515/515), done. Total 515 (delta 251), reused 291 (delta 133) foo_repo_develop/ (develop) $ ls README.md docs foo_repo_develop/ (develop) $ git remote add new_origin ssh://git@git.example.com:7999/hogehoge/foo_doc foo_repo_develop/ (develop) $ git push new_origin Counting objects: 76, done. Delta compression using up to 8 threads. Compressing objects: 100% (50/50), done. Writing objects: 100% (74/74), 1.95 MiB | 0 bytes/s, done. Total 74 (delta 14), reused 65 (delta 11) To ssh://git@git.example.com:7999/hogehoge/foo_doc * [new branch] develop -> develop
- featureブランチは、developと同じようにする。
- 書きかけのfeatureブランチはfeature/spec_updateで、コミットはしてある(original_repoにPushはしてない)
- 作業用のローカルリポジトリは
~/projects/foo_repo_feature
とします。
projects/ $ cd original_repo original_repo/ (develop) $ git checkout feature/spec_update Switched to branch 'feature/spec_update' Your branch is up-to-date with 'origin/feature/spec_update'. original_repo/ (feature/spec_update) $ cd .. projects/ $ git clone original_repo foo_repo_feature Cloning into 'foo_repo_feature'... done. projects/ $ cd foo_repo_feature foo_repo_feature/ (feature/spec_update) $ ls README.md docs src foo_repo_feature/ (feature/spec_update) $ git filter-branch --tree-filter 'rm -rf src' --prune-empty Rewrite 7b45ae1601a3db09d3bfadcc6107cffc2df08d9e (30/30) Ref 'refs/heads/feature/spec_update' was rewritten foo_repo_feature/ (feature/spec_update) $ ls README.md docs foo_repo_feature/ (feature/spec_update) $ git gc Counting objects: 519, done. Delta compression using up to 8 threads. Compressing objects: 100% (341/341), done. Writing objects: 100% (519/519), done. Total 519 (delta 257), reused 292 (delta 133) foo_repo_feature/ (feature/spec_update) $ ls README.md docs foo_repo_feature/ (feature/spec_update) $ git remote add new_origin ssh://git@git.example.com:7999/hogehoge/foo_doc foo_repo_feature/ (feature/spec_update) $ git push new_origin Counting objects: 19, done. Delta compression using up to 8 threads. Compressing objects: 100% (8/8), done. Writing objects: 100% (13/13), 50.55 KiB | 0 bytes/s, done. Total 13 (delta 5), reused 11 (delta 3) To ssh://git@git.example.com:7999/hogehoge/foo_doc * [new branch] feature/spec_update -> feature/spec_update
- 後始末
- 作業用の
foo_repo_develop
とfoo_repo_feature
を削除。 - 新たにリモートから新しいドキュメント用リポジトリをclone。
- 作業用の
projects/ $ rm -rf foo_repo_develop foo_repo_feature projects/ $ git clone ssh://git@git.example.com:7999/hogehoge/foo_doc foo_doc Cloning into 'foo_doc'... remote: Counting objects: 91, done. remote: Compressing objects: 100% (76/76), done. remote: Total 91 (delta 23), reused 0 (delta 0) Receiving objects: 100% (91/91), 2.00 MiB | 0 bytes/s, done. Resolving deltas: 100% (23/23), done. Checking connectivity... done.
これで新しいリポジトリで作業を再開出来ました。
元のリポジトリにあるドキュメントは普通に削除してコミットすればよいかと。(履歴を改変するほどのことはないかな)