yotiky Tech Blog

とあるエンジニアの備忘録

複数のリポジトリをモノレポ化する (multirepo to monorepo)

TL;DR

  • 複数のリポジトリをモノレポ化した際の備忘録
  • tomono スクリプトを修正したスクリプトを使用
  • リポジトリを移行することにフォーカスした記事
  • 以下の内容はこの記事では扱わない
    • モノレポ自体の説明や移行の検討
    • CI/CD、ツールなど
    • 運用ルール
  • サンプルのリポジトリを公開してるのでお試し可能

目次

概要

移行前

移行後

  • リポジトリ:monorepo
    • ModuleAフォルダ
      • READMEほか
    • ModuleBフォルダ
      • READMEほか
    • ModuleCフォルダ
      • READMEほか
    • ModuleDフォルダ
      • READMEほか

手順

1. 移行するものを決める

  • HEADのファイル、履歴、Git LFSファイル
  • タグ
  • ブランチ
  • issue
  • プルリク

今回は以下を移行対象とした

  • 履歴
  • Git LFSファイル
  • タグ
  • ブランチの一部

2. 新しいリポジトリを作る

新しいリポジトリを作成する。リポジトリの設定など必要な情報を引き継ぐ。

3. 準備

作業ディレクトリを作成する。

tomono リポジトリから以下のファイルを作業ディレクトリに保存する。

github.com

  • tomono
  • tomono.pushall
  • tomono.removeremotes

以下の内容を repos.txt という名前で作成する。

[git@github.com](mailto:git@github.com):yotiky/monorepo-test.ModuleA.git ModuleA
[git@github.com](mailto:git@github.com):yotiky/monorepo-test.ModuleB.git ModuleB
[git@github.com](mailto:git@github.com):yotiky/monorepo-test.ModuleC.git ModuleC
https://github.com/yotiky/monorepo-test.ModuleD.git ModuleD ModuleD lfs

4. リポジトリを移行する

Git Bashを起動して作業ディレクトリに移動する。

以下の内容を順に実行していく。

export MONOREPO_NAME=Monorepo
export MONOREPO_BRANCHES="main|branch-3$|^ModuleD"

./tomono < repos.txt

cd Monorepo

git remote add origin git@github.com:yotiky/monorepo-test.monorepo.git

../tomono.removeremotes  < ../repos.txt
../tomono.pushall ../merged_branches.txt

5. 検証

  • ブランチの作成、プルリク、マージが行えるか
  • git lfs fetch --all でGit LFSのチェック
  • アプリなどの動作確認

補足

サンプルリポジトリ

  • リポジトリでタグ、ブランチなどを設定済み
  • ModuleBはModuleCをサブモジュールとして参照
  • ModuleDはGit LFSを利用

tomono スクリプト

  • 異なるリポジトリの同じ名前のブランチは1つにマージされる
    • 例) ModuleA/main、ModuleB/mainは、origin/mainにマージ
  • タグはリポジトリ名で名前空間毎に割り振られる
    • 例) ModuleA/release1、ModuleB/release1
  • LFSを使ってる場合はSSHではなくHTTPSのアドレスを指定する
  • repos.txt は最後に空行が必要
  • MONOREPO_BRANCHES正規表現が使える
    • "main|develop" - mainまたはdevelopブランチのみ
    • "release.*" - releaseで始まる全てのブランチ
    • ".*" - 全てのブランチ

注意点

フィーチャーブランチ

フィーチャーブランチなど、ブランチを複数持っていく場合は、移行後のリポジトリでマージのコンフリクトが発生するので注意する必要がある。
移行前に最新にしていたとしても、移行の過程で各ブランチにファイルを追加、移動するコミットが入ることになる。フィーチャーブランチで変更していたものは基本的に衝突することになる。
ファイルの削除やリネームを行っていた場合、コンフリクトの解消では解消できないのでより注意が必要である。マージしようとした時にフィーチャーブランチでファイルを削除していたとしても、そもそも移行すること自体がファイルの追加であるため、追加されていないファイルを削除することができない状態となるようだ。一度追加したmainブランチで解消した上で削除するなどする必要があった。(Fork上)

できる限り少ないブランチを対象にすることをおすすめする。

Git LFSファイル

今回修正したスクリプトは、git lfs push する時にブランチを指定している。 ブランチに関わらずすべてのLFSファイルを引っ越したい場合は、元のリポジトリに新リポジトリをremoteとして追加して、git lfs push <新リポジトリ> --allして、新リポジトリ側にPUSHしてしまうのが良いだろう。

移行元リポジトリLFSをPUSH

手順の新しいリポジトリを作成した後に、移行元のリポジトリ、今回だとModuleDで以下の作業を実施する。

git lfs fetch --all
git remote add monorepo git@github.com:yotiky/monorepo-test.monorepo.git
git lfs push monorepo --all
git remote remove monorepo

サンプルリポジトリ

ModuleA~D

Monorepo