🕌

サブモジュールを使ったリポジトリ間の共通パーツ管理

2024/03/14に公開

目的

共通ソースを効率的に管理

下記で、repository1内のcommonとrepository2内のcommonは全く同じ。
このようなケースではソース管理をどうするのがよいだろう?
その一つの手段としてサブモジュール管理が有効。

Project
├── repository1
│	└── app
│	  ├── common
│	  ├── ...
│	  └── ...
└── repositpry2
 	└── app
 	  ├── common
 	  ├── ...
 	  └── ...

手順

1. 共通パーツ(common)を新規にリポジトリに切り出す。

共通パーツ(common)は個別のリポジトリで管理したほうが楽なので、commonリポジトリを新規作成。
ここで、作成されるリポジトリのURLをxxxxx@○○○○○.git.backlog.com:common.gitとする。

2. repository1,repository2から共通パーツ(common)を削除

repository1,repository2では共通パーツ(common)をソース管理したくないので、
repository1/app/commonとrepository2/app/commonを一旦削除。

共通パーツ(common)をサブモジュールとして追加

repository1に追加

Project$ cd repository1
Project/repository1$ git submodule add xxxxx@○○○○○.git.backlog.com:common.git app/common

repository2に追加

Project$ cd repository2
Project/repository2$ git submodule add xxxxx@○○○○○.git.backlog.com:common.git app/common

上記により、以下のファイルが自動で生成・編集される。

repository1/.gitmodules

[submodule "app/common"]
	path = app/common
	url = xxxxx@○○○○○.git.backlog.com:common.git

repository2/.gitmodules

[submodule "app/common"]
	path = app/common
	url = xxxxx@○○○○○.git.backlog.com:common.git

repository1/.git/config

...(省略)
[submodule "app/common"]
        active = true
        url = xxxxx@○○○○○.git.backlog.com:common.git

repository2/.git/config

...(省略)
[submodule "app/common"]
        active = true
        url = xxxxx@○○○○○.git.backlog.com:common.git

サブモジュールの最新化

共通パーツ(common)リポジトリに修正が入った場合は、repository1とrepository2のサブモジュールを最新化しなければならない。

repository1のcommonを最新化したいときは、Project/repository1ディレクトリに移動して以下を実行。
repository2のcommonを最新化したいときは、Project/repository2ディレクトリに移動して以下を実行。

$ git submodule update --init --recursive

差分について

repository1やresository2では、以下のようにapp/commonが差分として認識されますが、ここではサブモジュールのコミットポインタが5aa0e5f20b79f49e9022f8df95823c597d1401ebのような形で記録されます。

もし、コミットポインタが古ければ最新のコミットポインタに更新。

git submodule update --remote --merge

上記のコマンドで、サブモジュールのリモートリポジトリから最新の変更をフェッチし、サブモジュールをそのリモートの最新コミットに更新できます。

コミットポインタの差分をpushして完了です。

追記

サブモジュールの参照は相対パスでもできるので、たびたび修正が発生する共通パーツであれば、相対パスを使ったほうが楽。

Project
├── repository1
│	└── app
│	  ├── common
│	  ├── ...
	  └── ...
├── repositpry2
│	└── app
│	  ├── common
│	  ├── ...
│	  └── ...
└── common

repository1にサブモジュール追加

Project/repository1$ git submodule add ../common.git app/common

repository2にサブモジュール追加

Project/repository2$ git submodule add ../common.git app/common
repository1/.gitmodules
[submodule "app/common"]
	path = app/common
	url = ../common.git
repository2/.gitmodules
[submodule "app/common"]
	path = app/common
	url = ../common.git

Discussion