はじめに
それまでのコミット履歴をsquashしたりしているなど、たいへん荒っぽいことをやっています
remote repositoryにプッシュ後にやったりすると、間違いなくややこしいことになります
(筆者はこのときsvn環境でひとりローカルgitだったので…)
やりたかったこと
gitのRootが
Root
├ dirA
└ dirB
└ subDirC ←ここ
└.git
だったのを
Root ←ここ
└.git
└ dirA
└ dirB
└ subDirC
にしたい
補足
ブランチを複数切っていた(ただし,結局ブランチは整理)
一応いくつか方法は調べたが,
Subtree→ブランチがめためたになる
SubModule→よくわかんない
ということで、以下の方法を使った
やったこと
Filter-branchを使った
-
Root
ディレクトリ配下から、現在のgitのルートディレクトリ すなわちdirB/subDirC
を抜いたものを、.gitと同階層=subDirC
にコピー
(Root
の親ディレクトリがカレントディレクトリの状態でfind ./Root -type f -not -iwholename '*/subDirC*' -print0 | xargs -0 cp --parents -p -t ./Root/dirB/subDirC
などするとよいと思う)
Root
├ dirA
└ dirB
└ subDirC
├ .git
└ Root
├ dirA
└ dirB
└ (subDirC以外のdirBのなかみ)
~
2. master
ブランチに、1でコピーしたRoot
配下をadd&commit
3. ブランチが生えまくってるとうざいことに気づき、不要なブランチを整理、枝分かれ1つ(と言ってもFast-forward)だけ (feature_hoge
)に。なお今回のきっかけになったdirB外におよぶ変更については歴史修正後につぎはぎすることにして退避した
4. master
ブランチで git rebase -i --root
して、First commit以外、2.のコミットまでを全部Squash, First commit時にRoot
が存在する状態にしておく
5. feature_hoge
にCheckout(このときmaster
からはdetachされている), git rebase master
し、すでにRoot
のいる時空のmaster
からfeature_hoge
を生やす
6. feature_hoge
でgit filter-branch
をつかって以下の操作
git filter-branch --tree-filter 'mkdir Root/dirB/subDirC ; find ./ -mindepth 1 -maxdepth 1 -not -path "*Root*" -not -path ".git*" | xargs -I% mv % Root/dirB/subDirC' HEAD --all
(2でコピー後のRoot
を起点とし、本来subDirC
があるべきところにフォルダを作ってRoot
とカレントディレクトリとgitディレクトリ以外を移動、移動後の状態で全ブランチの歴史を書き換える。)
Root
├ dirA
└ dirB
└ subDirC
├ (subDirCの元々のなかみ) ← find ./ -mindepth 1 -maxdepth 1 -not -path "*Root*" -not -path ".git*"
で指定する
├ .git
└ Root
├ dirA
├ dirB
└ subDirC ← mkdir Root/dirB/subDirC
で作成
└ subDirCのなかみ ← find (略) |xargs -I% mv % Root/dirB/subDirC' HEAD --all
で移動
当然ですが、こんなことやるとfilter-branch前後でコミットIDが変わってしっちゃかめっちゃかになります
7. subDirC
の元々のなかみのうち、Git管理外のファイルが移動されないまま残るので、様子を見つつ整理する
8. git filter-branch -f --subdirectory-filter Root/ -- --all
して、gitのルートディレクトリを1階層ずらす(これにより、gitのルートディレクトリ・.gitの場所はそのまま、Root(コピー後)が消滅、その配下が1階層上に上がる。相対的には目標のディレクトリ構成に)
Root
├ dirA
└ dirB
└ subDirC ←ここがgitのRootなのは相変わらず
├ .git
├ dirA ← 1階層上にくる
└ dirB ← 1階層上にくる
└ subDirC
当然ですが、こんなことやるとfilter-branch前後でコミットIDが変わってしっちゃかめっちゃかになります
9. subDirC
の名前をRoot
に変える
Root
├ dirA
└ dirB
└ Root ← リネーム
├ .git
├ dirA
└ dirB
└ subDirC
~
10. もとのSVN Repo内にぶちこむ ← ※ 筆者の環境で必要だっただけです
11. なんかSVNが改行コードSensitiveだけど適当にごまかす ← ※ 筆者の環境で必要だっただけです
12. 必要に応じて9で作った方のRootを本来の場所に移動とかするといいんじゃないでしょうか
参考文献
あったはずなんだけどメモしてない!ごめんなさい!