🔄
Git submoduleが空のときの解決方法と基本的な使い方
問題
サブモジュールディレクトリを設定しているリポジトリをcloneしたときに、サブモジュールディレクトリが空になっていた。
結論
git clone
した後、サブモジュールも表示させたい場合は、以下のようにコマンドを実行する。
# サブモジュールを初期化して取得
git submodule update --init
Git submoduleとは
Git submoduleとは、Gitリポジトリ内に別のGitリポジトリを含めるための仕組みです。
- 親リポジトリにサブモジュールを含めることができる
- 幅数のプロジェクトで共通のコードを管理する
- などの用途で使われる。
今回は、obsidianのノートにzennなど、別のリポジトリを組み込むために使用。
今回対応した方法
1. 現在の状況を確認
$ git submodule status
-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa repository-name1
-bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb repository-name2
-
先頭の記号
-
-
: サブモジュールが初期化されていない(git submodule update --init がまだ) -
-
+
: サブモジュール内で変更がある(親が参照するコミットとズレている) -
U
: サブモジュールにマージ競合がある
-
-
コミットハッシュ
- 例: aaaaaaaa...
- サブモジュールが固定されている特定のコミット
→ ディレクトリは存在するが、サブモジュールが初期化されていない。
2.サブモジュールを初期化
$ git submodule update --init
Submodule 'repository-name1' (https://github.com/username/repository-name1.git) registered for path 'repository-name1'
Submodule 'repository-name2' (https://github.com/username/repository-name2.git) registered for path 'repository-name2'
Cloning into '/Users/soto/p/my-obsidian-notes/repository-name1'...
Cloning into '/Users/soto/p/my-obsidian-notes/repository-name2'...
Submodule path 'repository-name1': checked out 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
Submodule path 'repository-name2': checked out 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
→ サブモジュールが初期化され、内容が取得された。
3. 結果を確認
$ git submodule status
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa repository-name1 (heads/main)
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb repository-name2 (heads/main)
先頭の -
が消えて、スペースになっていることが確認できる。
git submodule init
と git submodule update --init
の違い
git submodule init
: サブモジュールを初期化する(ファイルは取得しない)
1. ファイルを取得するためには、git submodule update --init
を実行する必要がある。
実行例
サブモジュールを初期化する:
$ git submodule init // サブモジュールを初期化する
Submodule 'repository-name1' (https://github.com/username/repository-name1.git) registered for path 'repository-name1'
Submodule 'repository-name2' (https://github.com/username/repository-name2.git) registered for path 'repository-name2'
-
役割:
-
.gitmodules
に書かれた サブモジュールの設定をローカルに登録 するだけ - 実ファイルはまだ取得しない
-
-
実行後の状態:
-
.git/config
にサブモジュールの URL などが追記される - サブモジュールディレクトリは空のまま
-
-
用途:
- 「サブモジュールの登録だけして、まだダウンロードはしたくない」場合
サブモジュールのファイルを取得したい場合は、以下のコマンドを実行する:
$ git submodule update --init
Cloning into '/Users/soto/p/my-obsidian-notes/repository-name1'...
Cloning into '/Users/soto/p/my-obsidian-notes/repository-name2'...
Submodule path 'repository-name1': checked out 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
Submodule path 'repository-name2': checked out 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'
git submodule update --init
: サブモジュールを初期化&ファイルを取得
2. 初期化したあと、ファイルを取得する。
$ git submodule update --init
-
役割:
-
init
の処理を含みつつ、さらにファイルを取得 - 親リポジトリが参照する 特定のコミット でサブモジュールをチェックアウト
-
-
実行後の状態:
- サブモジュールの実体がディレクトリ内に展開される
-
用途:
- クローン直後に サブモジュールの中身も含めて使いたい場合
- 一般的にはこちらを使うことが多い
そもそも最初からサブモジュールも含めてcloneしたい
方法1: 順次実行
git clone --recurse-submodules git@github.com:username/main-repo.git
- 調べていると
--recursive
というオプションも出てくるが、これは古くからあるコマンドとのことで、現在は--recurse-submodules
を使用が推奨されるとのこと。 - 機能的には全く同じ。
方法2: 並列実行
git clone --recurse-submodules -j8 git@github.com:username/main-repo.git
-
-j8
コマンドをつけると、サブモジュールのクローンが並列で実行され、時間を短縮できる。 - ただし、並列実行すると、メモリ使用量が増加する可能性がある。
おわりに
そもそも、obsidianのディレクトリにzennの記事などのファイルもまとめたいと思ったのが、サブモジュールというもの自体を知ることになったきっかけ。
存在すら知らなかったので、まだまだわからないことだらけである。引き続き学んでいきたい。
Discussion