Gitのサブモジュール機能を使ってプロジェクトを管理してみよう
こんにちは、okutani(@okutani_t)です。Gitのサブモジュール(submodule)についてイマイチよく分かっていなかったので、備忘録も兼ねて記事にしてみました。
Gitのサブモジュール機能を使うと、プロジェクトで管理しているGitリポジトリとは別に、独立したリポジトリをプロジェクトに含ませることができます。
サブモジュールを含んだプロジェクトでは、プッシュ・プルをおこなってもサブモジュール側のリポジトリには影響がない、といった特徴があります。
他の特徴としては、サブモジュールはあくまで特定コミットを示すポイントを追加したディレクトリに埋め込むものです。
本記事ではGitのバージョンは1.8.5以上を対象としています。それ以下のバージョンでは使えないコマンドなどあるので注意してください。
では、さっそくGitのサブモジュールの使い方を見ていきましょう。
参考Git のサブモジュールってどんなもの? – Qiita
参考git submodule は癖がすごいとの噂だったが素直につきあっていけそうという話 | deadwood
スポンサーリンク
もくじ
プロジェクトにサブモジュールを追加する
まずは、Gitで管理しているプロジェクトにサブモジュールを追加してみます。適当にsubmodule_testプロジェクトを作成。
$ mkdir submodule_test && cd submodule_test
$ git init
$ echo test > test.txt
$ git add .
$ git commit -m "first commit"
次のコマンドで、現在のプロジェクトにサブモジュールを追加します。今回はあらかじめ「hello」というリポジトリを用意してあります。詳細は後述します。
サブモジュールを追加するには「git submodule add」コマンドを使います。
$ git submodule add https://github.com/okutani-t/hello.git
もし、ディレクトリを指定したい場合は以下のとおりです。以下の例では、vendorディレクトリ以下にhelloという名前で配置しています。
$ git submodule add https://github.com/okutani-t/hello.git vendor/hello
git submodule addは内部で「git submodule init」が実行され、初期化処理がおこなわれています。
このサンプルのサブモジュール(hello)は、あらかじめ、先ほどと同じ手順で作成しておいたGitHubで管理している別プロジェクトです。hello.txtファイルのみを持っており、helloとだけ記述されています。
$ ls hello
hello.txt
$ cat hello/hello.txt
hello
では、「git status」でリポジトリの状態を確認してみます。
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD ..." to unstage)
new file: .gitmodules
new file: hello
「.gitmodules」と「hello」が追加されていることが確認できました。
追加された.gitmodulesファイルの中身を見てみます。
$ cat .gitmodules
[submodule "hello"]
path = hello
url = https://github.com/okutani-t/hello.git
helloという名前で設定されていることが確認できます。ローカルのパスと、リモートのURLがそれぞれ記述されていますね。
ちなみに、.git/configファイルの中身にも、次のように追記されていることが確認できます。
$ cat .git/config
...省略...
[submodule "hello"]
url = https://github.com/okutani-t/hello.git
サブモジュールは追加をおこなったあと、プロジェクト側でコミットしておく必要があります。次のコマンドでコミットを実行。
$ git commit -m "add submodule: hello"
これでプロジェクトにサブモジュールを含ませることができました。
以下のコマンドでサブモジュールの状態を確認できます。
$ git submodule status
または
$ git submodule
サブモジュールの状態が表示されているのが確認できればOKです。
リポジトリをGitHubにプッシュしてみる
GitHubにプッシュしてみます。
$ git remote add origin https://github.com/okutani-t/submodule_test.git
$ git push origin master
このように、helloサブモジュールが追加されていることが確認できました。
サブモジュール名の隣に書いてある「5224fb8」は、サブモジュールを追加した時点のhelloのコミットを指しています。
サブモジュールをアップデートしてみる
次に、「サブモジュールが更新された際、現在のプロジェクトへサブモジュールの最新版を反映する」といったことをしてみます。
helloプロジェクト(サブモジュール)の中身を適当にごにょごにょして、次のコマンドでアップデートしてみます(GitHub上でhello.txtの中身をhello2にしてから下記を実行しました)。
$ git submodule foreach git pull
上記のコマンドでは、「git submodule foreach」コマンドを使って、それぞれのサブモジュールにgit pullをおこなわせています。なので、現在のプロジェクトすべてのサブモジュールがアップデートされます。
これでhello.txtの中身がhello2になっていればOKです。
$ cat hello/hello.txt
hello2
サブモジュールがきちんと最新版に更新されていることが確認できました。
ステージング・コミットしてプッシュしておきましょう。
$ git add .
$ git commit -m "update submodule hello: hello2"
$ git push origin master
これで、リモートのリポジトリにもサブモジュールの更新が反映されました。
上記のように、helloプロジェクトのコミット番号が変更されているのが確認できます。クリックするとhello.txtの内容がhello2になっているのが確認できるかと思います。
サブモジュールを含んだプロジェクトをクローンする
サブモジュールを含んだプロジェクトをGitHubで管理する、というところまで見てきました。次に、そのプロジェクトをクローンする方法を見てみましょう。
以下のコマンドで、サブモジュールを含んだプロジェクトを一発でクローンすることができます。
$ git clone --recursive https://github.com/okutani-t/submodule_test.git
もし、すでにクローン済みで、サブモジュールを含んでいない場合、次のコマンドでサブモジュールを落としてくることができます。
$ git clone https://github.com/okutani-t/submodule_test.git
$ git submodule update --init --recursive
もしくは、次の手順でも同様にサブモジュールを落としてくることができます。
$ git clone https://github.com/okutani-t/submodule_test.git
$ git submodule init
$ git submodule update
基本的には一番上の「git clone --recursive
」を使えばOKかと思います。
サブモジュールを編集する
先ほどは、helloプロジェクトをリモート上で直接書き換えましたが、今度はサブモジュールをローカルで直接編集して、リモートリポジトリに反映させてみましょう。
helloディレクトリに移動し、新しく作業用ブランチを切ります。作業用ブランチを切らないと、のちにdetached HEAD状態になってしまうので注意。
$ cd hello
$ git checkout -b work
hello.txtの中身を変更、ステージング・コミットします。
$ echo hello3 > hello.txt
$ git add .
$ git commit -m 'fix submodule: hello'
masterブランチへマージ。
$ git checkout master
$ git merge work
リモートのhelloへプッシュします。
$ git push origin master
作成した作業用ブランチは不要なので削除してもOK。
$ git branch -d work
現在のプロジェクトに戻り、ステージング・コミットします。
$ cd ..
$ git add .
$ git commit -m "hello3 rewite to hello.txt"
リモートリポジトリにプッシュ。
$ git push origin master
リモートのプロジェクトからhelloプロジェクトに移動して、hello3になっていればOKです。
サブモジュールを削除する
サブモジュールを削除したい場合は以下のコマンドを実行します。
$ git submodule deinit hello
$ git rm -rf hello
$ rm -rf .git/modules/hello
これでサブモジュールを削除できます。
もしくは「git submodulesで間違えて追加したときの削除手順 – Qiita」のようなやり方もあるようです。参考にしてください。
まとめ
Gitのサブモジュール機能を使って、独立した別プロジェクトを現在のプロジェクトに追加する方法を見てきました。
Rubyであればgem、PHPであればcomposerなどのツールがありますが、gitで同じようなことをおこないたい場合はサブモジュール機能を使うと良いですね。
Gitのサブモジュールは直接編集してリモートリポジトリに反映させることができるので、自分で管理しているプロジェクトのメンテナンスなども楽におこなうことができます。
今回利用したテストのリポジトリはこちらです。
参考okutani-t/submodule_test: git submoduleの練習
Gitユーザーの参考になれば幸いです。
Web開発のお仕事を募集しています
フリーランスのエンジニアとして、Webシステム開発のお仕事依頼を随時募集しています(現在の業務量によってお受けできない場合もあります)。
「Ruby on Rails」「JavaScript(jQuery, Reactなど)」「HTML + CSS」を用いたシステム開発、「Heroku」等を用いたサーバー構築・運用、「Git」や「GitHub」を利用したソーシャルコーディングなどに対応しています。
ご依頼を検討している方は、下記リンク本ブログからのお問い合わせ、もしくはokutaniのポートフォリオからご連絡ください。
LINKお問い合わせ
スポンサーリンク