【Git】リポジトリ内に別のリポジトリを組み込む方法【Gitサブモジュール】

アプリのコードはGitでバージョン管理しているけど、「このアプリが使うデータやライブラリ」の管理はどうしていますか?
- 「アプリのデータも、過去の変更を追ったり、誰が何を直したか見たい!」
- 「アプリのコードとは別に、データやライブラリだけを独立して管理したい!」
そう考えているなら、Gitのサブモジュールという機能がとても役に立ちます。
この記事では、Gitで管理しているアプリのフォルダの中に別のリポジトリを組み込む方法を解説します。
[rotc_mokuji]
サブモジュールとは
Gitのサブモジュールとは、「あなたのメインのプロジェクトの中に、別のGitリポジトリ(別のプロジェクト)を組み込む」 ための機能です。
もっと簡単に言うと、まるで一つの大きな箱の中に、小さな箱をそのまま入れる」 ようなイメージです。
サブモジュールの作成方法
サブモジュールは以下のコマンドで追加することができます。
git submodule add <リポジトリのURL> <ローカルの保存先パス(省略可)>
メインのリポジトリとサブモジュールの関係
メインのリポジトリはサブモジュールの中身のファイル自体を管理しません。
その代わりに、「別のリポジトリの、この時点(特定のコミット)の状態を参照する」 という情報だけを記録します。
メインのプロジェクトとサブモジュールが、お互いに独立してバージョン管理されているので、メインのプロジェクトをgit clone
しただけでは、サブモジュールのフォルダは空っぽです。
サブモジュールの中身を使うためには、git submodule init
やgit submodule update
といった追加のコマンドを実行して、初めて中身のファイルがダウンロードされる仕組みになっています。たとえば以下のコマンドで行うことができます。
git submodule update --init --recursive
また、メインリポジトリをクローンするときにサブモジュールを含めて一度にクローンしたいときは--recursive
オプションをつけてクローンします。
git clone --recursive <リポジトリのURL>
リポジトリ内に別のリポジトリを組み込む
ここでは例として、Gitで管理しているアプリのフォルダの中に、データ管理用の別のGitリポジトリを組み込みます。
目標構成
以下の構成を目標にします。メインリポジトリはクローン済みとします。
your-project/
├─ .git/
├─ .gitmodules # ← submodule 設定が入る
├─ media/
│ └─ data/ # ← ここが別リポジトリ(submodule)
└─ src/ …
.gitignore
でmedia/
を無視してOK。submodule は「gitlink」として親リポジトリに登録されるため、media/
を無視していても media/json
は追跡されます(後述の例外指定は任意)。
サブモジュールを新規に追加する場合
media/data
が空の場合の方法を解説します。
サブモジュールとして追加したいリポジトリをGitHub/GitLab 等に先に作っておきます。
次にプロジェクトのルートディレクトリ(your-project/
)でサブモジュールをmedia/data
に追加します。コマンドは以下の通りです。
git submodule add <リモートリポジトリのURL> media/data
その後上記コマンドで生成された.gitmodules
と gitlink
をメインリポジトリへコミットします。
git commit -m "Add data submodule at media/data"
既存の JSON ファイルを submodule に移行する場合
次はすでに media/data
にファイルがある場合です。
ここでもあらかじめサブモジュール用のリポジトリをGitHub/GitLab 等に先に作っておきましょう。
準備ができたら media/data
の中身をいったんどこかに移して空にします。
GUI上で手動で移してもよいですし、
ターミナルで作業をするなら、以下のコマンドをプロジェクトルートディレクトリ(your-project/)で実行します(一例です)。
mkdir -p ~/tmp/data-backup # ホームディレクトリに退避
cp -a media/data/. ~/tmp/data-backup
次にプロジェクトのルートディレクトリ(your-project/
)でサブモジュールをmedia/data
に追加しましょう。(空の submodule として追加します。)
コマンドは以下の通りです。
git submodule add <リモートリポジトリのURL> media/data
その後上記コマンドで生成された.gitmodules
と gitlink
をメインリポジトリへコミットします。
git commit -m "Introduce media/data as submodule"
次に退避したファイルを今設定したサブモジュール側へ移動させます。
まず、プロジェクトのルートディレクトリ(your-project/
)からサブモジュールのディレクトリへ移動しましょう。
cd media/data
その後退避したファイルをサブモジュールへ移動させます。
cp -a /tmp/data-backup/. .
移動させたらサブモジュール側のリポジトリへCommit/Push しましょう。
git add .
git commit -m "Seed JSON assets from project (initial import)"
git push origin main # ※ デフォルトブランチ名に合わせる
最後に、メインリポジトリにポインタ更新を反映します。
# 親にポインタ更新を反映
cd ../..
git add media/data
git commit -m "Point submodule to initial data commit"
おまけ: submodule を削除したい場合
追加したサブモジュールを削除するには以下のように行います。
-
git rm -f media/json
を実行 -
.gitmodules
の該当エントリを削除 git commit
を実行.git/config
の submodule エントリを掃除(必要なら)- 作業ツリー上の
media/json/
を手動削除(必要なら)
まとめ
この記事ではGitのサブモジュールという機能を使用して、Gitで管理しているアプリのフォルダの中に別のリポジトリを組み込む方法を解説しました。
Gitのサブモジュールとは、「あなたのメインのプロジェクトの中に、別のGitリポジトリ(別のプロジェクト)を組み込む」 ための機能で、
アプリ本体と、ライブラリやデータを完全に独立した別のリポジトリとして管理しながら、一つのプロジェクトとして扱うことができます。