🧩

これでやっとgit submodulesに入門できた

2025/02/03に公開

概要

git submodulesを使うことで、複数に分かれたリポジトリを1つにまとめて開発することができます。
例: フロントエンドとバックエンドでリポジトリを分けているが、開発での起動時は1つのディレクトリ配下に配置してDocker等で起動したい。
そのためにgit submodulesの基本的な使い方を学んでみたので、その記録として記事を書いてみます。

言葉の定義

  • 親リポジトリ: git submodulesを配置する(他リポジトリを参照する)ためのリポジトリ
  • サブモジュール: git submodulesとして親リポジトリから参照されるリポジトリ
  • 親リポジトリ側のサブモジュールの参照: git submodulesとして親リポジトリが参照するサブモジュールのコミットハッシュ

今回使用したリポジトリ例

今回の作業は以下リポジトリで行いましたので、具体例を知りたい場合は以下を参照ください。

$ tree -L 1   
.
├── README.md
├── application(今回使うのはこのディレクトリのみ)
├── cache
├── database
├── docker-compose.yml
└── web

submodulesを使用する流れと解説

以下の手順は全て親リポジトリ配下で作業を行うこととなります。financial-statement-frontendリポジトリやfinancial-statement-backendリポジトリ配下では作業しないことに注意してください。

1. 親リポジトリ側でgit submodulesの設定を行う

financial-statement-frontendリポジトリを参照するための設定コマンドを実行します。
以下コマンドを実行することで、https://github.com/shin4488/financial-statement-frontend リポジトリの参照を親リポジトリのapplication/frontendディレクトリ配下に配置します。

$ git submodule add https://github.com/shin4488/financial-statement-frontend application/frontend

同様に、financial-statement-backendリポジトリを参照するための設定コマンドを実行します。
https://github.com/shin4488/financial-statement-backend リポジトリの参照を親リポジトリのapplication/backendディレクトリ配下に配置します。

$ git submodule add https://github.com/shin4488/financial-statement-backend application/backend

上記で親リポジトリが参照する内容は、サブモジュールの特定コミットとなります。(サブモジュールのファイルやディレクトリそのものが親リポジトリに入ってくるわけではない)

2. 1のgit submodulesの参照をcommit・pushする

親リポジトリ側で行ったgit submodulesの設定をcommit・pushします。
親リポジトリで以下を実行します。

$ git add application/frontend application/backend
$ git commit -m "hogehogeコミットメッセージ"
$ git push origin main

以下のようにサブモジュールへの参照が作成されたことをGitHub上で確認できます。

これでサブモジュールの設定は完了です。
例えば、docker-compose.ymlでapplication/frontendやapplication/backendに対するDockerの設定を行うことで、親リポジトリ上でfrontendとbackendのDocker同時起動などが可能となります。(便利🎉)

以降では、frontendやbackendの内容を変更するような開発の流れも合わせて確認していきましょう!

3. サブモジュール側の変更を行う

まずは親リポジトリ側でapplication/frontend/README.mdを以下のように変更してみます。

途中略

+frontend test

application/frontend直下に移動した上で、上記の変更をcommit・pushします。
以下はサブモジュール(financial-statement-frontendリポジトリ)へのcommit・pushとなります。

$ cd application/frontend
$ git add REDAME.md
$ git commit - "add: test submodules for frontend"
$ git push origin main

すると、GitHub上では以下のようにサブモジュール(financial-statement-frontendリポジトリ)が更新されます。

この時点では、まだ親リポジトリのapplication/frontendの参照先コミットハッシュは更新されていないことに注意してください。
あくまでサブモジュール(financial-statement-frontendリポジトリ)のみが変更されています。

4. 親リポジトリ側のサブモジュールの参照を変更する

次に、親リポジトリでルートディレクトリに移動した上で、application/frontendの参照先コミットハッシュ更新をcommit・pushします。
以下はこれは親リポジトリへのcommit・pushであることに注意してください。

$ cd ../../ # 親リポジトリでルートディレクトリに移動する
$ git status # 以下のようにapplication/frontendに新規コミットが存在することで、差分として表示される
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
  (commit or discard the untracked or modified content in submodules)
        modified:   application/frontend (new commits)
$ git add application/frontend
$ git commit -m "update: frontend moudle"
$ git push origin main

GitHub上でサブモジュールへの参照リンクをクリックして、サブモジュールのリポジトリを見てみます。

すると、README.mdにfrontend testが追加されたコミットを参照していることが分かるのでokです。

5. 親リポジトリ側の最新のサブモジュール参照を取り込む

複数人で開発を行う場合、他のメンバーが親リポジトリ側でサブモジュールへの参照先コミットハッシュを更新することがあります。
この更新を自分のローカル環境に取り込んで、サブモジュールの内容を更新してみましょう!

git pull origin main

これを行うことで、親リポジトリ側のサブモジュールの参照先コミットハッシュのみが更新されます。
(参照先コミットハッシュの更新 ≠ 参照先サブモジュール内のディレクトリやファイル自体の更新 → 詳細は6で解説します)

6. 親リポジトリ側で参照しているサブモジュールのディレクトリ・ファイルを更新する

git pull origin mainを行っただけでは、親リポジトリ側でサブモジュールの内容をエディタ上で開いた時に、サブモジュールの更新前のディレクトリ・ファイルが開かれて、更新後の状態にはなっていません。
(参照しているコミットハッシュのみが更新されて、サブモジュール内のディレクトリやファイル自体はまだ更新されていない)
サブモジュール内のディレクトリやファイル自体も更新するために、以下を実行します。

git submodule update --init --recursive

オプションに関して、まだクローンされていないサブモジュールがある場合は初期化(--init)し、もしサブモジュール内にさらにサブモジュールがある場合は再帰的に更新(--recursive)します。

さいごに

以上の1〜6を理解することで、git submodulesを使用した基本的な開発を行うことができることでしょう!

Discussion