🌴

Gitで異なる2つのリポジトリを連結(統合)する方法

課題

以前書いたコードを見直していると煩雑なリポジトリ構成(複数親ディレクトリ:1リポジトリ)だったため1つのリポジトリに統合して管理したいと考えた。

git fetchコマンドを利用することで過去の変更履歴を引き継いだまま複数のリポジトリを一つにまとめることが可能らしい。ということで実践してみた。

準備

  • ベースとなるリポジトリの作成
  • 素材となるリポジトリ(1つ以上)

まずはベース(複数のリポジトリをまとめる親)となるリポジトリを作りましょう。といっても普段通りに作ればおkです。

~$ mkdir base_dir
~$ cd base_dir
base_dir$ git init
base_dir$ touch README.md

README.md 内は各自適当に操作してください。

素材となるリポジトリは base_dir と同じ階層に置いておくと操作が簡単です。
※ 階層が異なっていたり、Github上に置いていても同様に連結することができます。

実践

まずはベースリポジトリ(base_dir)にリモートリポジトリと登録しましょう。リモートリポジトリと聞くとGithub等のサーバ上のリポジトリを想像される方いるでしょう。別にサーバに無くて、ローカルの別のリポジトリでもリモートリポジトリとして登録することができます。

# ベースリポジトリにリモートリポジトリとして対象のリポジトリを登録する
base_dir$ git remote add rimote_repo ../remote_dir

remote_repo の部分はfetchするときの名称なのでorigin以外であれば何でもおkです。 remote_dir はベースリポジトリに連結する素材となるリポジトリが置いてあるディレクトリを指定します。

一連のディレクトリ構造を表すと以下のようになっているかと思います。

.
├── base_dir
│   ├── .git
│   │   ├── HEAD
│   .   .
│   .   .
│   .   .
│   │   └── refs
│   │       ├── heads
│   │       └── tags
│   └── README.md
└── remote_dir
    ├── .git
    │   ├── HEAD
    .   .
    .   .
    .   .
    │   └── refs
    │       ├── heads
    │       └── tags
    └── README.md
# ベースリポジトリ内からリモートリポジトリの中身を取得する
base_dir$ git fetch rimote_repo

取得すると、ベースリポジトリ内に新しいブランチとして登録されるので、マージします。

# リモートリポジトリの内容をマージする
base_dir$ git merge --allow-unrelated-histories rimote_repo/master

ベースとなるリポジトリの内容よりも古い情報をマージする可能性が高いので--allow-unrelated-historiesオプションをつけています。

これは Git2.9 より無関係な2つのブランチをmergeするときには--allow-unrelated-historiesオプションをつけないとmergeできなくなったからです。

Doc: https://git-scm.com/docs/git-merge#Documentation/git-merge.txt---allow-unrelated-histories

これで2つの異なるリポジトリを統合することができました

補足

参考:
Git で複数のリポジトリをまとめたり、逆に切り出したりする

統合する素材となるリポジトリのコミットユーザやメールアドレスを変更する場合は以下の記事を参照:
ユーザを間違えたままgithubにpushしたときの書き換え

都内で働くiOSエンジニア(2年目)