【Git】コミット履歴を保持したまま特定ディレクトリを独立リポジトリへ切り出す(分割)Gitコマンド完全ガイド

公開日: 2026年09月12日

1. 概要とユースケース

プロジェクトの成長や構成の見直しに伴い、単一のリポジトリ(モノレポ)で管理していた特定サービスや共通コンポーネント(例: 共通 Nginx リバースプロキシ、共有ライブラリ、API ゲートウェイなど)を、「独立した別の Git リポジトリとして切り出したい」 という場面があります。

しかし、単純にファイルを別のディレクトリへコピー&ペーストして新しく git init してしまうと、これまでの開発で積み重ねてきたコミット履歴(git log や git blame)がすべて失われてしまいます。

Git の標準機能である git subtree split を活用することで、特定ディレクトリに関係する過去のコミット履歴(コミットメッセージ、日時、変更差分)を 100% 保持したまま、新しい独立リポジトリへ安全に切り出す ことができます。


2. 切り出しの仕組みと全体の流れ

graph TD
    subgraph OldRepo ["① 元プロジェクトのコミット履歴"]
        direction TB
        C1["Commit 1: プロジェクト初期化"]
        C2["Commit 2: nginx/ 初期設定追加"]:::target
        C3["Commit 3: nginx/ SSL設定修正"]:::target
        C4["Commit 4: アプリの新機能追加"]
        
        C1 --> C2 --> C3 --> C4
    end

    subgraph Split ["② git subtree split による履歴抽出"]
        direction TB
        Target["nginx/ ディレクトリのコミットのみを抽出"]
        TempBranch(["抽出ブランチ<br>(nginx-standalone)"]):::branch
        Target --> TempBranch
    end

    subgraph NewRepo ["③ 新しい独立リポジトリ (reverse-proxy)"]
        direction TB
        NC1["Commit 1: nginx/ 初期設定追加"]:::target
        NC2["Commit 2: nginx/ SSL設定修正"]:::target
        NC1 --> NC2
        Note["✅ 過去の作成者・日時・コミットログが完全保持される"]:::note
    end

    C2 -.->|抽出| Target
    C3 -.->|抽出| Target
    TempBranch ==>|git pull で取り込み| NewRepo

    classDef target fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e40af;
    classDef branch fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0369a1;
    classDef note fill:#f0fdf4,stroke:#16a34a,stroke-width:1.5px,color:#15803d;

3. ステップ別コマンド手順

以下のシナリオを例として手順を解説します:

  • 元リポジトリ: /path/to/main-project
  • 切り出したいディレクトリ: nginx/
  • 新リポジトリの作成先: /path/to/reverse-proxy

Step 1: 元リポジトリで特定ディレクトリの履歴を抽出する

元リポジトリのディレクトリに移動し、git subtree split コマンドを実行して、対象ディレクトリ(-P)のコミット履歴だけを抽出した新しいブランチ(-b)を作成します。

cd /path/to/main-project

# nginx ディレクトリの履歴だけを抽出して「nginx-standalone」ブランチを作成
git subtree split -P nginx -b nginx-standalone

解説:

  • -P <ディレクトリ名>: 抽出対象のサブディレクトリパスを指定します。
  • -b <ブランチ名>: 抽出した履歴を格納する新しいブランチ名を指定します。

Step 2: 抽出されたブランチのコミット履歴を確認する

意図したディレクトリに関する過去のコミット履歴だけが正しく抽出されているか確認します。

git log --oneline nginx-standalone

出力例のように、対象ディレクトリに関するコミットログがルート階層を基準として並んでいれば成功です。


Step 3: 新しいディレクトリを作成して Git リポジトリを初期化する

切り出し先となる新しいディレクトリを作成し、空の Git リポジトリを作成します。

# 新リポジトリ用のディレクトリを作成
mkdir -p /path/to/reverse-proxy
cd /path/to/reverse-proxy

# Git リポジトリの初期化
git init -b master

Step 4: 抽出したブランチの履歴を引き込む (pull)

元リポジトリのパスと抽出ブランチを指定して、コミット履歴を新リポジトリに取り込みます。

git pull /path/to/main-project nginx-standalone

取り込み完了後、ファイル一覧とコミット履歴を確認します:

# ファイルが展開されているか確認
ls -la

# 過去のコミット履歴がそのまま残っているか確認
git log --oneline

これで、過去のコミットログ・作成日時・変更履歴を完全維持した独立リポジトリが完成しました!


Step 5: 元リポジトリ側から不要ディレクトリを削除して整理する

新リポジトリへの移行が確認できたら、元リポジトリ側にある旧ディレクトリを削除し、変更をコミットします。

cd /path/to/main-project

# ディレクトリの削除
git rm -r nginx

# 変更をコミット
git commit -m "Nginx環境を独立リポジトリ(reverse-proxy)へ切り離し"

Step 6: 一時的に作成した抽出ブランチを削除する(後片付け)

Step 1 で作成した一時ブランチは役目を終えたため、安全に削除します。

git branch -D nginx-standalone

4. 注意点と運用のヒント

  1. Git 管理外ファイル(.gitignore)のコピー漏れに注意
    • 設定ファイルや環境変数(.env、API トークン、秘密鍵等)など、.gitignore で Git 管理から除外されていた実ファイルは git subtree split では移行されません。
    • 新ディレクトリへ手動で cp -a して権限(パーミッション)を維持して配置する必要があります。
  2. サブモジュール(Git Submodule)との使い分け
    • リポジトリ同士の親子関係を厳密に保ちたい場合は Submodule を検討しますが、特定モジュールを「完全に独立して各サービスから切り離して運用したい」場合は、本記事の完全分割(独立リポジトリ化)が最もシンプルでトラブルが少なくなります。

5. まとめ

コマンド 役割
git subtree split -P <dir> -b <branch> 特定サブディレクトリのコミット履歴だけを抽出して新ブランチを作成
git pull <元リポジトリパス> <抽出ブランチ> 抽出した履歴を新しい Git リポジトリに取り込み
git branch -D <抽出ブランチ> 作業完了後の一時ブランチを安全に削除

この手順を踏むことで、「これまでの試行錯誤の歴史」を一切犠牲にすることなく、ディレクトリの分割・リポジトリの独立化を美しく実現できます。