Gitを使った分散開発管理14 – サブモジュールを使用する

Git

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Gitのサブモジュール

複数のリポジトリをあたかも1つのリポジトリ内にあるかのように扱いたいケースがあったとします。
例えば、メインのアプリケーションと、そのアプリ内で使用するライブラリを別々に管理する必要がある場合などです。
Subversionを使用している場合にはsvn:externalsを使用すれば解決できると思いますが、Gitの場合はサブモジュールを使用します。

サブモジュールを使うと、Gitのリポジトリを別のリポジトリのサブディレクトリとして扱うことができるようになります。
今回はこのサブモジュールについてご紹介します。

サブモジュールをつかってみる

では実際に試していきます。

サブモジュール用リポジトリを作成

では新しくリポジトリを2つ用意してサブモジュールを試してみます。1つ目のリポジトリはlibRepという名前で作成します。
これはもうひとつのリポジトリのサブモジュールとして追加されるJavaScriptのライブラリです。
ではlibRepリポジトリを作成しましょう。

% cd /path/your/gitreps
% mkdir libRep
% cd libRep
% git init

scriptディレクトリを作成し、その中にlib.jsファイルを作成します。

function hello() {
  alert("hello");
}

addしてコミットします。

% git add .
% git commit -m "initial commit"

メインリポジトリを作成

appRepディレクトリを作成し、git initで初期化します。

% cd /path/your/gitreps
% mkdir appRep
% cd appRep
% git init

ここでgit submoduleコマンドを実行してみましょう。これはリポジトリのサブモジュールを表示するコマンドです。
サブモジュールはないので、当然なにも表示されません。

%git submodule                                               

では先程作成したサブモジュールを追加します。追加するにはgit submodule addコマンドを使用します。
その後git submoduleコマンドを実行すれば、サブモジュールが表示されます。

%git submodule add ../libRep lib                            
Cloning into 'lib'...
done.
%git submodule                                              
 38365ebe934ad02990d07bb766b87bd83c60d145 lib (heads/master)

最後にコミットを行えばサブモジュールの取り込みとこのリポジトリの初期化が完了です。

%git status                                                 
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#	new file:   .gitmodules
#	new file:   lib
#
%git commit -m "add submodule"                               
[master (root-commit) 35d2d64] add submodule
 2 files changed, 4 insertions(+), 0 deletions(-)
 create mode 100644 .gitmodules
 create mode 160000 lib

サブモジュールを使用したリポジトリをcloneしてみる

次に、サブモジュールを使用しているリポジトリをcloneした場合の動作を見てみます。 cloneする前にappRepにhtmlファイルを1つコミットしましょう。index.htmlという名前で下記内容をコミットします。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <script src="lib/script/lib.js"></script>
  <title>Hello Git!</title>
</head>
<body>
  <h2 id="toc-hello-git">Hello Git!</h2>
  <input type="button" onclick="hello()" value="click"  />
</body>
</html>

ではappRepをcloneRepという名前でcloneします。

% cd /path/your/gitreps
% git clone appRep cloneRep

cloneしたリポジトリ内のlibディレクトリを見てみると、何もはいっていません。
git submobuleコマンド実行すると、先頭に「-」がついています。

%cd cloneRep/                                                      
%git submodule                                             
-38365ebe934ad02990d07bb766b87bd83c60d145 lib

これはサブモジュールがまだ初期化されていないことを示しています。初期化しましょう。
git submodule init <サブモジュール名>で初期化します。ただ、これだけでは初期化しただけなので、
git submodule update <サブモジュール名>で、サブモジュールへ変更をpullします。

%git submodule init lib 
%git submodule update lib                                  
Cloning into 'lib'...
done.
Submodule path 'lib': checked out '38365ebe934ad02990d07bb766b87bd83c60d145'

これでlibRepの内容がとりこまれ、cloneRepも使用できるようになりました。

まとめ

今回はサブモジュールを基本的な使用方法をご紹介しました。
1つ注意点として、サブモジュールは最新のコミットを常に追跡するわけではなく、addした時点でのコミットを使用します。
もしサブモジュールを最新のコミットに更新したい場合、下記のようにしてサブモジュールを更新しましょう。

% git submodule foreach 'git pull'