半年ほど前のことでうろ覚えなのですが、pixivで複数のリポジトリを統合したときの方法を紹介します。
AAAAAリポジトリとBBBBBリポジトリを統合し、ZZZZZという大きなリポジトリを作成します。もちろんコミットログを統合前まで遡れるようにするのが絶対条件です。
最終形↓
- ZZZZZ
- .git
- AAAAA
- BBBBB
filter-branch
まず、新しくgit clone AAAAA
してきます。(なぜなら、このディレクトリはこの後使い捨てられるので、pushされてないbranchとがあると困るからです)
次にcd AAAAA
して、次のコマンドを実行します。
git filter-branch --index-filter \
'git ls-files -s | sed "s@\t\"*@&AAAAA/@" |
GIT_INDEX_FILE=$GIT_INDEX_FILE.new \
git update-index --index-info &&
mv $GIT_INDEX_FILE.new $GIT_INDEX_FILE || true' -- --all
(「全てのブランチ」である必要がないなら "-- --all" を "HEAD" に変えればよいです)
git filter-branch
で履歴をごっそり書き換えます。どのように書き換えるかというと、git ls-files
で全てのファイルを列挙し、それに"AAAAA/"というプレフィックスを付けてmv
するというようにです。
つまり、このリポジトリの中のファイルは全部AAAAAというディレクトリの中のファイルだったことにします。2万コミットほどあったpixivでは30分ぐらいかかっていた記憶があります。
この段階で
- AAAAA
- AAAAA
- .git
というディレクトリ構造になっているはずです。
ローカルディレクトリをgit remote add
これをBBBBBのほうにも適用し、例えばBBBBBのほうのディレクトリに入って、
git remote add localAAAAA /path/to/the/AAAAA
のようにします。(/path/to/the/AAAAAは先ほどの.gitがあるディレクトリです)
git fetch localAAAAA
git merge --allow-unrelated-histories localAAAAA/main
とすると、AAAAAのmainだったブランチがBBBBBに統合され、
- BBBBB
- BBBBB
- AAAAA
- .git
のようになるはずです。あとはこの新しいBBBBBをZZZZZリポジトリにpushするだけです。
制約
filter-branchではコミットログは残りますが、コミットハッシュは変わってしまいます。
main以外のブランチを持ってくる場合はそれぞれmergeする必要があります。全てのブランチの場合は簡単な方法があるんでしょうか?