STORES Product Blog

こだわりを持ったお商売を支える「STORES」のテクノロジー部門のメンバーによるブログです。

モノレポに `git subtree` で別リポジトリを統合・運用する

はじめに

この記事は STORES Advent Calendar 2025 の 8 日目の記事です。

こんにちは。ima1zumiです。私は以前 bongo というモノレポに、別途開発されていた cdp-dashboard というフロントエンドのリポジトリを統合しました。

リポジトリを統合する手段はいくつかありますが、今回は git subtree を採用しました。なぜ subtree だったのか、実際にどう運用したのかを紹介します。

背景

これまで別々のリポジトリとして管理されていた bongo(Rails / React Router)と cdp-dashboard(Nuxt)ですが、開発・デプロイのライフサイクルやチームの体制変更、cdp-railsbongo に統合されたことに伴い、一つのリポジトリとして管理するニーズが出てきました。

外部リポジトリを取り込む際、真っ先に思いつくのは git submodule ですが、

  • 別リポジトリで管理し続けるメリットがなかった
  • 管理が煩雑になる

という理由で見送りました。

git subtree は、外部リポジトリの内容をあたかも最初からそのディレクトリにあったかのように取り込め、かつ履歴も保持できる点が今回の要件にマッチしていました。

導入手順

実際の導入は非常にシンプルです。

1. リモートの追加

まず、取り込みたいリポジトリをリモートとして追加します。

git remote add cdp-dashboard https://github.com/...
git fetch cdp-dashboard

2. subtree add で取り込み

--prefix オプションで配置先のディレクトリを指定して取り込みます。

# cdp-dashboard ディレクトリ配下に main ブランチの内容を取り込む
git subtree add --prefix=cdp-dashboard cdp-dashboard main

これで、cdp-dashboard ディレクトリ配下にファイルが展開され、コミット履歴も移行されます。

実際にPRを出した際は、git subtree add によって commit が移行されるため巨大PRができあがります。私が作成したPRでは、4383 commits, 264files changedの差分となりました。これを検証するのは不可能なので、レビューではディレクトリ名・置き場所が正しいことだけを見てもらいました。

運用の実際:差分の取り込み

統合後も、元の cdp-dashboard リポジトリ側で開発が続く場合や、段階的な移行期間中は同期が必要です。

同期も以下のコマンド一発で行えます。

git subtree pull --prefix=cdp-dashboard cdp-dashboard main

手順を素振りしたPRでも、問題なく差分が取り込めることを確認しました。

運用手順としてドキュメント化しておけば、チームメンバーも迷わず操作できます。

ハマりどころとTips

  • ディレクトリ構成prefix を指定することで名前空間をきれいに分離できます。今回はルート直下に cdp-dashboard を置きましたが、元々モノレポ構成で他のディレクトリ構成と混ざらないので置き場には悩みませんでした。
  • コンフリクト: 基本的には発生しにくいですが、親リポジトリ側で cdp-dashboard 配下を直接いじり、かつ元リポジトリでも変更があった場合はコンフリクト解消が必要です。原則「同期方向は一方通行(元→親)」にするか、完全に統合して元リポジトリを廃止するか、運用ルールを決めておくのが吉です。
  • 歴史改竄: git logがそのまま移行されるので、移行先リポジトリの開発開始より前のcommitであっても記録されます。とはいえ、困るのはリポジトリのfirst commitを遡ろうとしたときくらいかなと思います。

まとめ

巨大なRailsリポジトリへの機能統合として git subtree は非常に手軽で強力な選択肢でした。

「別リポジトリでPoCしていた機能を本体に組み込みたい」「管理コスト削減のためにリポジトリを減らしたい」というケースでは、ぜひ git subtree を検討してみてください。