2つの Git リポジトリーを合成する

そういうことはあったりなかったりしますよね

git remote add repo-b path/to/repo-b
git fetch repo-b
git merge --allow-unrelated-histories --no-ff repo-b/master

ガッチャン

*   3879620 2017-02-24
|\  osyoyu  (HEAD -> master) Merge remote-tracking branch 'repo-b/master'
| * b4507af 2017-02-24
|   osyoyu  Initial commit of repo b
* b6c4065 2017-02-24
  osyoyu  Initial commit of repo a

確かに亜空間から b4507af が発生していることが分かる

–allow-unrelated-histories について

これは実は Git 2.9 から必要になった比較的新しいオプションで、指定しないと

% git merge repo-b/master
fatal: refusing to merge unrelated histories

と言われてしまう。

このオプションが入ったのにはちょっと面白い経緯がある。Linux kernel に新しいファイルをコミットしようとした人が GitHub のヘルプを見つつ、新しいリポジトリを作り、 kernel にそれを git merge したところあっさり成功してしまって、それに誰も気づかないまま Linux kernel に親のないコミットが追加されてしまったらしい。

結局Linusが気づき共通の親コミットを持たないブランチ同士はデフォルトでマージできないようにするべきという話になったようだ。

ちなみに Linux kernel には親のないコミットが、上記のものを含め4つあるらしい。1つはもちろん本当に最初のコミット、残り2つはそれぞれ別の repo で開発されていた btrfs と greybus の最初のコミットだそうな。

The Biggest and Weirdest Commits in Linux Kernel Git History で他の Linux kernel repo おもしろ話(たとえば親が66個あるコミットがあるなど)がいろいろ読めてグッド。