【Git】コミット履歴を保持したまま複数リポジトリをサブディレクトリとして統合(モノレポ化)する

公開日: 2026年08月17日

1. 概要とユースケース

プロジェクトが成長するにつれて、「フロントエンド」と「バックエンド」のように別々で管理していた 2 つ以上の Git リポジトリを、1 つのリポジトリ(モノレポ構成)にまとめたい 場面があります。

単にファイルをコピー&ペーストしてコミットすると、これまでのコミット履歴(git loggit blame)がすべて消えてしまいます

本ドキュメントでは、過去のコミット履歴(作成者・コミット日時・メッセージ)を 100% 保持したまま、特定サブディレクトリにリポジトリを統合するための標準的な Git コマンド をまとめます。


2. 統合の基本手順(git subtree を使う方法)

git subtree add を使用することで、別リポジトリのブランチツリーを親リポジトリの指定ディレクトリ(--prefix)へマージできます。

【全体の流れ】

[統合元リポジトリ (例: /path/to/sub-repo)]
                 │
                 ▼ git remote add & fetch
[統合先リポジトリ (例: /path/to/main-repo)]
                 │
                 ▼ git subtree add --prefix=dir_name
[main-repo/dir_name/ に全コミット履歴付きで合流完了!]

ステップ別コマンド解説

Step 1: バックアップブランチを作成する(推奨)

万が一の操作ミスに備えて、統合前の状態を別名ブランチに保存しておきます。

cd /path/to/main-repo

# 現在の master (または main) からバックアップブランチを作成
git branch backup/before-merge

Step 2: 統合先リポジトリで統合元をリモートとして追加する

ローカルパスまたはリモート URL(GitHub 等)をリモートリポジトリとして一時登録します。

# ローカルディレクトリの場合
git remote add sub-repo-remote /path/to/sub-repo

# GitHub等のリモートURLの場合
# git remote add sub-repo-remote [email protected]:username/sub-repo.git

Step 3: 統合元のブランチ情報をフェッチする

統合元リポジトリの全コミット履歴を取得します。

git fetch sub-repo-remote

Step 4: git subtree add で指定フォルダとして取り込む

履歴を保持したまま、指定したプレフィックス(サブディレクトリ)配下にマージします。

# sub-repo-remote の main ブランチを sub-dir/ ディレクトリに取り込む
git subtree add --prefix=sub-dir sub-repo-remote main

[!IMPORTANT] --squash オプションは付けないでください--squash を指定すると過去のコミットが 1 つにまとめられてしまい、個別コミット履歴が失われます。過去ログをすべて残したい場合は --squash なしで実行します。


Step 5: 一時登録したリモートを削除する

マージが完了したら、不要になったリモート設定をクリーンアップします。

git remote remove sub-repo-remote

Step 6: 履歴の統合結果を確認する

コミットグラフを表示して、統合元リポジトリのコミットがツリーとして合流していることを確認します。

git log --graph --oneline -n 20

3. 統合後のディレクトリ階層整理(履歴を壊さない git mv の方法)

取り込んだ後で「フォルダの階層が深すぎる」「フォルダ名を変更したい」という場合は、通常の mv ではなく git mv を使用します。

例1: サブディレクトリの中身を親ディレクトリに展開する場合

# sub-dir/nested/ 配下のファイルを sub-dir/ 直下に移動
git mv sub-dir/nested/* sub-dir/

# 隠しファイル(.env.example や .gitignore 等)も個別に移動
git mv sub-dir/nested/.gitignore sub-dir/.gitignore

# 空になったフォルダを削除
rmdir sub-dir/nested

例2: 取り込んだフォルダ名をリネームする場合

# sub-dir を app-frontend にリネーム
git mv sub-dir app-frontend

[!TIP] git mv を行った後に git status を確認すると renamed: fileA -> fileB (100%) と表示されます。 この状態でコミットすることで、ファイルのリネーム後も git log --follow <ファイルパス> で過去の変更履歴を途切れずに追跡できます。


4. コピペ用チートシート(一括実行用)

リポジトリ /path/to/repoB の内容を、リポジトリ /path/to/repoAsub-project/ フォルダ配下に履歴ごと取り込むテンプレートです。

# 1. 統合先リポジトリに移動
cd /path/to/repoA

# 2. バックアップブランチを作成
git branch backup/before-merge

# 3. 統合元リポジトリを一時リモートとして追加
git remote add temp-remote /path/to/repoB

# 4. フェッチ
git fetch temp-remote

# 5. subtree で指定フォルダに取り込み (履歴全保持)
git subtree add --prefix=sub-project temp-remote main

# 6. 一時リモートを削除
git remote remove temp-remote

# 7. 履歴の確認
git log --graph --oneline -n 15

5. よくある質問・注意点 (FAQ)

Q1. .gitignore で除外されているファイル(.env.local やビルド成果物)はどうなる?

Git 管理されていないファイルは git subtree ではコピーされません。必要な環境変数ファイル(.env.local 等)がある場合は、手動で新しいディレクトリにコピーしてください。

Q2. 統合元のリポジトリ自体は削除していい?

統合先でコミット履歴・ファイルが正常にマージされていることを git log やファイル一覧で確認できれば、元のリポジトリディレクトリは削除(またはバックアップ退避)しても問題ありません。

Q3. リネーム後のファイルの過去ログを見るには?

ファイル名を移動した後の履歴を確認する場合は、--follow オプションを付けて実行します。

git log --follow -p app-frontend/src/index.ts