LoginSignup
0
0

More than 3 years have passed since last update.

git ルート階層を上げたい!

Last updated at Posted at 2019-10-03

はじめに

それまでのコミット履歴をsquashしたりしているなど、たいへん荒っぽいことをやっています

remote repositoryにプッシュ後にやったりすると、間違いなくややこしいことになります

(筆者はこのときsvn環境でひとりローカルgitだったので…)

やりたかったこと

gitのRootが

Root
├ dirA
└ dirB
 └ subDirC ←ここ
  └.git

だったのを

Root ←ここ
└.git
└ dirA
└ dirB
 └ subDirC

にしたい

補足

ブランチを複数切っていた(ただし,結局ブランチは整理)

一応いくつか方法は調べたが,

Subtree→ブランチがめためたになる
SubModule→よくわかんない

ということで、以下の方法を使った

やったこと

Filter-branchを使った

  1. 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_hogegit 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を本来の場所に移動とかするといいんじゃないでしょうか

参考文献

あったはずなんだけどメモしてない!ごめんなさい!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0