他のGitリポジトリをプロジェクトに追加したいときありませんか?
たとえば、他の人が作ったライブラリや、自分が別で管理しているコードを使いたいとき、毎回コピー&ペーストするのは面倒ですね。そんなときに便利なのが Gitのサブモジュール という機能です。ただし、サブモジュールは便利な分、使い方を間違えるとトラブルの原因になります。このページでは、サブモジュールの基本と、よく使う操作について、わかりやすくまとめています。
サブモジュールとは?
サブモジュールとは、外部のGitリポジトリを、自分のプロジェクトの中に「リンク」として組み込む機能です。コードを直接コピーするのではなく、ある特定のコミットを参照する仕組みです。
イメージとしては、「ここには、このバージョンのこのリポジトリを使用する」という形で明示的に指定することができます。
よくある使い方
- 複数のプロジェクトで共有するライブラリを入れるとき
- 何度も使い回すコードをまとめたいとき
- メインのリポジトリとは別に、外部コードを管理したいとき
基本コマンドまとめ
サブモジュールを追加する
例:
git submodule add https://github.com/example/awesome-lib.git submodules/awesome-lib
このコマンドは、外部リポジトリを現在のプロジェクトの特定のパスにサブモジュールとして追加します。
サブモジュール付きでクローンする
例:
example: git clone --recurse-submodules https://github.com/user/app.git
このコマンドを使うことで、リポジトリをクローンする際にサブモジュールも同時に取得できます。--recurse-submodules
を付けないと、サブモジュールの中身は空のままになるため、初回のクローン時にはこのオプションを付けるのが推奨されます。
サブモジュールを最新の状態にする
設定されているブランチの最新コミットを取得します。
サブモジュールの更新をコミットする
git commit -m "Update submodule"
例:
git add submodules/awesome-lib
git commit -m "Update submodule"
サブモジュールの中身を更新しただけでは、親リポジトリには変更として認識されません。
サブモジュールが参照しているコミット(バージョン)を変更した場合は、その変更を親リポジトリにも反映させる必要があります。
そのためには、サブモジュールのパスを git add
してからコミットすることで、親リポジトリに新しい参照先を記録できます。
サブモジュールを削除する
rm -rf .git/modules/path/to/submodule
例:
git rm -f submodules/awesome-lib
rm -rf .git/modules/submodules/awesome-lib
その後、以下のファイルから手動で該当エントリを削除してください:
.gitmodules
.git/config(あれば)
これらを削除することで、サブモジュールに関する情報をリポジトリから完全に取り除くことができます。
常に特定のブランチ(例:main)を追いかけたい場合
.gitmodules に以下のように設定できます:
[submodule "submodules/awesome-lib"]
path = submodules/awesome-lib
url = https://github.com/example/awesome-lib.git
branch = main
設定後は以下で更新:
git submodule update --remote
サブモジュールを更新する基本の流れ
1. サブモジュールのフォルダに入るcd submodules/awesome-lib
2. コードを編集する
通常のリポジトリと同様に、ファイルを編集します
3. サブモジュール内でコミット&プッシュする
4. メインプロジェクトに戻る
5. サブモジュールの参照を更新してコミットするgit add submodules/awesome-lib
git commit -m "Update submodule to latest commit"
この流れを守ることで:
- サブモジュールの変更が 親リポジトリに正しく反映 される
- チームメンバーが git pull したときにも 正しい状態で同期 される
- サブモジュールを直接編集した際に起こりがちな "detached HEAD" 問題 を防げる
サブモジュールを使うのが向いているケース
- 外部リポジトリが別の開発サイクルで動いているとき
外部のライブラリやツールが独立して開発されており、自分のプロジェクトとは異なるタイミングで更新される場合に便利です。必要なときだけ明示的にアップデートできます。 - 履歴や責任範囲を明確に分けたいとき
サブモジュールを使えば、メインプロジェクトとは別に履歴を保てるため、バグや変更の責任範囲が明確になります。 - 外部コードを「読むだけ」で使いたいとき
外部のコードをプロジェクトに取り込みたいが、基本的には自分で編集せず参照するだけ、というケースに適しています。
サブモジュールを避けたほうがよいケース
- サブモジュール内のコードを頻繁に変更する必要がある場合
サブモジュールは特定のコミットを参照する仕組みのため、頻繁な修正には向いていません。親リポジトリとの連携も都度手動で更新する必要があり、手間が増えます。 - チームにGitの操作を何度も説明するのが難しい場合
サブモジュールの仕組みは少し複雑で、clone や pull 時に追加の操作が必要です。Gitに不慣れなメンバーがいる場合、運用ミスが発生しやすくなります。 - 他のパッケージ管理ツールで代替できる場合
JavaScript の npm や Python の pip、Swift の Swift Package Manager など、言語や環境に合った依存管理ツールを使うほうが、より簡単かつ安全に運用できます。
まとめ
Gitサブモジュールは、外部のバージョン管理されたコードをプロジェクトに安全に組み込むための強力な手段です。しかし、単発のコード取り込みには適していません。使用する前に「なぜ使うのか」を明確にし、正しい運用方法をチームで共有することが重要です。コマンドを習得したり、ドキュメント化しておくことで、長期的には非常に便利なツールとなります。