【Git】サブモジュールとは?メリットや使い方を具体的に解説

Web開発

はじめに

皆さんはGitでコードを管理する際、プロジェクトの中に別のリポジトリを含めたい場面に遭遇したことはないでしょうか。
大規模なプロジェクトでは、複数のリポジトリを組み合わせて開発を行うケースがよくあります。
しかし、単純にフォルダの中へコピーするとバージョン管理が混在してしまい、思わぬトラブルにつながることもあります。

そこで役立つのがGitサブモジュールという仕組みです。
サブモジュールを使うことで、1つのリポジトリに外部のリポジトリを取り込むことができます。
これにより、各リポジトリの変更履歴を独立して管理しながら、全体としての一貫したバージョンも保ちやすくなります。

本記事では、Gitサブモジュールの概念から導入手順、実際の運用上の注意点まで具体的に解説します。
コード例も示していきますので、実際の作業イメージをつかみながら学んでみてください。

この記事を読むとわかること

  • Gitサブモジュールの基本的な仕組み
  • サブモジュールを使うメリットと具体的な導入手順
  • サブモジュールを更新・削除する方法
  • 実務での活用シーンや運用のポイント

サブモジュールとは

Gitサブモジュールとは、あるリポジトリの中で別のリポジトリを参照管理する仕組みです。
たとえば、大きなアプリケーションの一部として、便利なライブラリや別プロジェクトを取り込みたい場合に役立ちます。
サブモジュールを設定すると、メインのリポジトリ(ルートリポジトリ)に加えて、外部リポジトリを同じバージョン管理の枠組み内で扱うことができます。

実務での活用シーン

以下のようなケースでサブモジュールが多用されます。

共通ライブラリを複数プロジェクトで利用する

自作の共通コードやライブラリをまとめて管理し、別プロジェクトからも直接参照して開発を進めることができます。
コピー・ペーストよりもミスが少なく、バージョンアップ時に対応しやすいのが特徴です。

大規模なプロジェクトで部分的に独立したチームが開発

フロントエンドとバックエンドでリポジトリを分けている場合や、複数のサービスを連携させる場合でも、それぞれをサブモジュールとして取り込むことで一元管理が可能になります。

外部ツールやライブラリを直接組み込む

OSSのライブラリなどをプロジェクト内で改変しながら使いたい場合にもサブモジュールが役立ちます。
変更点を追いやすくなり、修正を反映する際に混乱しにくいです。

サブモジュールを使うメリット

サブモジュールを導入することで得られる利点には、次のようなものがあります。

1. 変更履歴の明確化

サブモジュールは独立したリポジトリとしてバージョン履歴を保持しています。
そのため、メインのリポジトリのコミットとサブモジュールのコミットを切り離して管理できます。

2. 一貫した依存関係の保全

どのバージョンのサブモジュールを使っているかを正確に記録できるので、環境の再現性が高まります。
別の環境で同じコミットをチェックアウトすれば、サブモジュールも同じ状態に固定できるのが大きな強みです。

3. 管理が容易

複数のリポジトリをまとめて扱わなくてはいけないとき、サブモジュールによってそれぞれの更新履歴を分けたまま、一元的な管理を行いやすくなります。

4. チーム開発でのトラブル削減

別チームが管理するリポジトリを取り込む際でも、サブモジュールなら誤って直接コミットしてしまうリスクを抑えられます。
変更はそれぞれのリポジトリで完結するため、衝突や競合が起こりにくいです。

サブモジュールを導入する方法

実際にサブモジュールを導入する手順を見てみましょう。
ここでは、メインのリポジトリに外部のリポジトリを取り込み、必要に応じて更新する流れを整理します。

サブモジュールの追加

はじめに、メインのリポジトリが存在するディレクトリに移動し、サブモジュールを追加してみましょう。
以下のコード例では、https://github.com/example/awesome-library.git というリポジトリを libs/awesome-library ディレクトリとして取り込むケースを想定しています。

git submodule add https://github.com/example/awesome-library.git libs/awesome-library

コマンドが成功すると、.gitmodules という設定ファイルが生成され、サブモジュールのURLやパスが記録されます。
また、libs/awesome-library ディレクトリが作成され、その中に外部リポジトリの内容がクローンされます。

サブモジュールの初期化と取得

サブモジュールを追加しただけでは、他の開発メンバーが同じリポジトリをクローンした際、サブモジュールの中身が空の状態で取り込まれることがあります。
そのため、サブモジュールを利用する前に以下の2ステップを行うのが一般的です。

git submodule init
git submodule update

git submodule init

.gitmodules ファイルを元にサブモジュール情報を初期設定するコマンドです。

git submodule update

設定に基づいてサブモジュールの最新状態を取得してきます。

この2つのコマンドは、サブモジュールを正しく使うためのセットのように覚えておくと便利です。

サブモジュールを更新する方法

サブモジュールとして組み込んだリポジトリに対して、最新の変更を取り込みたい場合もよくあります。
その手順は、いくつかの方法に分けられます。

サブモジュール内での更新

サブモジュールとして組み込んだディレクトリに入り、通常どおりGit操作を行う方法です。
以下の流れで更新できます。

  1. サブモジュールのディレクトリに移動
  2. git fetchgit pull を実行
  3. 作業ブランチに変更を反映(あるいは新たなコミットを作成)
  4. メインリポジトリに戻り、サブモジュールの変更をコミット

具体的には、以下のように操作します。

cd libs/awesome-library
git pull origin main
cd ../..
git add libs/awesome-library
git commit -m "Update submodule to latest commit"

上記のコミットをメインリポジトリでプッシュすると、サブモジュールの指し示すコミットIDが更新され、他のメンバーも同じコミットをチェックアウトすれば統一された状態で取得できます。

メインリポジトリからの一括更新

メインリポジトリからすべてのサブモジュールを一括で更新する場合は、以下のコマンドを使うことがあります。

git submodule update --remote

このオプションを付けると、.gitmodules に記載されたブランチの最新コミットが取得されます。
ただし、意図せず全サブモジュールが更新されることもあるため、状況に合わせて運用するとよいでしょう。

サブモジュールを削除する方法

サブモジュールを誤って追加した、あるいはもう使わなくなった場合には削除することになります。
手動でディレクトリを消すだけでは正しく除外されないので、以下のステップで対応します。

  1. メインリポジトリの .gitmodules から対象サブモジュールの設定を削除
  2. .git/config 内の submodule.<name> セクションも削除(必要に応じて)
  3. サブモジュールのディレクトリ自体を削除
  4. 削除したことをコミット

例として、libs/awesome-library を削除する流れは次のようになります。

# .gitmodulesファイルをエディタで開き、[submodule "libs/awesome-library"] を削除
vi .gitmodules

# .git/configからも同様のセクションを削除
vi .git/config

# ディレクトリを削除
rm -rf libs/awesome-library

# 変更をコミット
git add .gitmodules
git commit -m "Remove submodule entry"
git rm --cached libs/awesome-library
git commit -m "Remove submodule directory"

このように複数段階を踏む必要があるのは、サブモジュール関連の情報が複数ファイルに書き込まれているためです。
誤って中途半端に削除すると、後々トラブルが起きる可能性があるので注意しましょう。

サブモジュールの削除手順を途中で中断すると設定ファイルだけが残ってしまうことがあります。
この状態でリポジトリをクローンすると正しくディレクトリが作られないなどの不整合が生じるので、一連の作業は完了まで行うことをおすすめします。

運用上の注意点

サブモジュールは便利な一方で、使い方を誤るとトラブルに見舞われやすい仕組みでもあります。
主な注意点をまとめてみましょう。

サブモジュールのバージョン固定

サブモジュールのコミットIDをメインリポジトリに記録する仕組み上、外部リポジトリの更新が頻繁に行われている場合は意図しないコミットで作業してしまうリスクがあります。
更新を行う場合は誰がいつ更新したのかを可視化し、コミットメッセージを丁寧に残しておくことが大切です。

サブモジュールのネスト

サブモジュールの中に、さらに別のサブモジュールを入れる構造も可能ですが、管理が複雑になります。
ディレクトリ階層が深くなるほど混乱しやすいので、特別な事情がなければ避けた方が無難です。

他のメンバーへの共有

チーム開発では、新たにサブモジュールを追加したら他のメンバーにも分かりやすい方法で周知してください。
メンバーがメインリポジトリをクローンしてから git submodule init / git submodule update を忘れていると、正しくファイルが取得できません。
運用ルールを決めておくとスムーズです。

サブモジュールを導入した際は、プロジェクトのREADMEなどにサブモジュール運用の手順を簡潔にまとめておくと、初めて参加する人でも混乱しづらくなります。

まとめ

Gitサブモジュールを活用することで、複数リポジトリを統合的に管理しやすくなります。
ライブラリの共有や別プロジェクトとの連携など、実務での利用シーンはさまざまです。
ただし、サブモジュールを追加・更新・削除する際は複数のファイルを編集しなければならない点に注意が必要です。

実際には、サブモジュールの仕組みに加え、チーム内でのガイドライン作成やリポジトリ構成のルール設定などが重要になります。
ぜひ、本記事の具体的な手順やポイントを参考にしながら、サブモジュールを安全かつ便利に運用してみてください。

Gitをマスターしよう

この記事で学んだGitの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。