GitのSubmoduleについて

submoduleの追加

リモートリポジトリlib.gitをローカルの異なるリポジトリにサブモジュールとして追加する。追加すると、.gitmodulesというファイルとlib.gitのクローンが作成される

> git submodule add <url>
> git submodule add -b <branch> <url>
> mkdir test
> cd test
> git init
Initialized empty Git repository in ...
> git submodule add ../repos/lib.git
Cloning into ...
done.
> ls
.  ..  .git  .gitmodules  lib

.gitmodulesにはリモートリポジトリのパスとローカルのどのリポジトリと結びついているかが記載されており、git submoduleコマンドを実行すると各サブモジュールとコミットIDが列挙される。つまり、サブモジュールは取り込んだ別のリポジトリのコミットIDのみを追跡している模様。

> cat .gitmodules
[submodule "lib"]
    path = lib
    url = ../repos/lib.git/

> git submodule
96b950f37e6f4d4d98418a5c52649d71a78eb490 lib (heads/master)

サブモジュールのリンク解除

以下のコマンドでリンクが解除される

> git submodule deinit <サブモジュール名>

リンクが切れると、自動的に参照するためにクローンされていたファイル群がなくなっている

> git submodule deinit lib
Cleared directory 'lib'
Submodule 'lib' (../repos/lib.git/) unregistered for path 'lib'
> ls lib
. ..

ただし、設定ファイルは残っているので、完全に不要になった場合は、git rmで.gitsubmoduleを削除する。

サブモジュールのリンク

サブモジュールを参照しているリポジトリをクローンしたり、上記のようにdeinitでリンクを解除すると、設定ファイルである.gitmodulesだけが存在した状態になっており、参照先のファイルのクローンが存在してない。

この状態で再度リンクしたい場合は、以下のupdateコマンドで--initオプションをつけて実行する。

> git submodule update --init
Submodule path 'lib': checked out '96b950f37e6f4d4d98418a5c52649d71a78eb490'

サブモジュールの更新

親のリポジトリを更新しても、サブモジュールの管理は別なので更新されることはない。サブモジュールをリモートの最新に更新したくなった場合は、以下のコマンドで更新することができる。

> git submodule update --remote
> git submodule update --remote
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /repos/lib
   d1860f3..5da7374  master     -> origin/master
Submodule path 'lib': checked out '5da7374ef39acfaf22180ed10c262a150f827280'