151
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

Organization

履歴を残したまま複数のgitリポジトリを統合する

半年ほど前のことでうろ覚えなのですが、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 tmpA /path/to/the/AAAAA

のようにします。(/path/to/the/AAAAAは先ほどの.gitがあるディレクトリです)

git fetch tmpA
git merge tmpA/master

とすると、AAAAAのmasterだったブランチがBBBBBに統合され、

  • BBBBB
    • BBBBB
    • AAAAA
    • .git

のようになるはずです。あとはこの新しいBBBBBをZZZZZリポジトリにpushするだけです。

制約

filter-branchではコミットログは残りますが、コミットハッシュは変わってしまいます。

master以外のブランチを持ってくる場合はそれぞれmergeする必要があります。全てのブランチの場合は簡単な方法があるんでしょうか?

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
151
Help us understand the problem. What are the problem?