動機とゴール
古いリポジトリ B
に scala と java のプロジェクトが混在してて、scala は scala で リポジトリ A
に纏めたかった為。
- A
- scala-lib
- a-project
- scala-lib
- B
- scala-dir
- scala-project-1
- scala-project-2
- java-dir
- java-project
- scala-dir
こんな感じの2つの repository の B から scala 以下のプロジェクトディレクトリを
- A
- scala-lib
- a-prokect
- scala-project-1
- scala-project-2
- scala-lib
こんな感じに纏めたい。
以下のようにゴチャゴチャやらなくても git mv
すりゃいいじゃんという気もしますが、 repository B の java-dir
の commit log は残したくなかったので。
特定のディレクトリのみの git repository を作成する
B を clone する。履歴が書き変わるので、作業ディレクトリとは別に clone した方が良い。
git clone <B>
cd ~/B
B ディレクトリ で scala-dir 以下のディレクトリだけを全部持ってきたい場合
git filter-branch --prune-empty --subdirectory-filter scala-dir BRANCH-NAME
B/scala-dir/scala-project-1
と B/scala-dir/scala-project-2
が
B/scala-project-1
と B/scala-project-2
になります。
Bのディレクトリを更に改竄する
A/scala-lib/
以下に入れたい場合
git filter-branch --index-filter \
'git ls-files -s | sed "s@[[:cntrl:]]\"*@&scala-lib/@" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE || true' -- --all
を実行する。参照
(OSX で実行しています。)
B/scala-project-1
と B/scala-project-2
が
B/scala-lib/scala-project-1
と B/scala-lib/scala-project-2
になります。
A の reposiroty の入れたいディレクトリに上書きしているだけ。
A 直下に入れるのであればこの作業は不要。
A にマージする
cd ~/A
git remote add tmpB ~/B/
git fetch tmpB
git merge tmpB/master --allow-unrelated-histories
--allow-unrelated-histories
をつけないと怒られる。
これで、
A/scala-lib
に scala-project-1
と scala-project-2
が入りました。
但し filter-branch
実行で commit ID は変わってしまいます。(2回やってるけどどっちのオプションでも変わります。)