Visual Studio 18.9では、Git RepositoryウィンドウからGit Submoduleの追加・更新・削除を行えるようになりました。サブモジュールを依存ライブラリとして利用するだけなら、既定のRead-onlyのままで問題ありません。サブモジュール内のコードを編集・コミットする場合は、Tools→Options→Source Control→Gitを開き、Automatically activate multiple repositoriesをYes, include submodulesへ変更します。
この機能は、2026年8月11日に公開されたVisual Studio 2026 version 18.9.0で追加されました。従来のように、Submoduleを操作するたびにターミナルへ移動する場面を減らせます。(Microsoft Learn)
Visual Studio 18.9のGit Submodule管理で変わったこと
Visual Studio 18.9では、SubmoduleがVisual StudioのGit機能へ本格的に統合されました。
| 機能 | Visual Studio 18.9での動作 |
|---|---|
| Submoduleの表示 | Git Repositoryウィンドウに専用のSubmodulesセクションを表示 |
| 追加 | 親リポジトリへSubmoduleを追加 |
| 更新 | 登録済みSubmoduleを更新 |
| 削除 | 親リポジトリからSubmoduleを削除 |
| 変更確認 | Git Changesウィンドウでリポジトリごとの変更を確認 |
| リポジトリ切り替え | 親リポジトリとSubmoduleの階層関係をリポジトリピッカーに表示 |
| 自動検出 | ソリューションまたはフォルダーを開いたときにSubmoduleを検出 |
| 誤操作防止 | Submoduleは既定でRead-only |
検出されたSubmoduleは、通常のローカルリポジトリ一覧には混在せず、親リポジトリとの階層関係が分かる形で表示されます。複数のSubmoduleを利用するプロジェクトでも、リポジトリ一覧が必要以上に煩雑になりにくい設計です。(Microsoft Learn)
ただし、Visual Studio 18.9で改善されたのは操作画面です。Git Submodule自体の仕組みが変わったわけではありません。安全に運用するには、親リポジトリとSubmoduleが別々のリポジトリであることを理解しておく必要があります。
Git Submoduleは「フォルダー」ではなく別のリポジトリ
Git Submoduleは、あるGitリポジトリの中へ、別のGitリポジトリを組み込む仕組みです。Submoduleを含む側は「superproject」または親リポジトリと呼ばれます。
親リポジトリが記録する主な情報は、次の2つです。
.gitmodulesに保存されるSubmoduleのパスや取得元URLgitlinkとして記録されるSubmoduleの特定コミットID
つまり、親リポジトリはSubmoduleのファイルそのものではなく、「子リポジトリのどのコミットを使うか」を記録しています。(Git)
たとえば、次のような構成があるとします。
ProductApp/
├─ src/
├─ shared/
│ └─ CommonLibrary/ ← Git Submodule
└─ .gitmodules
親リポジトリProductAppが、CommonLibraryのコミットabc1234を参照している場合、別の開発者がSubmodule側へ新しいコミットdef5678を追加しても、親リポジトリが自動的に新しいコミットへ切り替わるわけではありません。
新しいバージョンを採用するには、Submoduleをdef5678へ進めたうえで、親リポジトリ側でも参照先の変更をコミットします。
この仕組みにより、共有ライブラリ側の更新によって親プロジェクトが突然壊れるのを防ぎ、動作確認済みのコミットへ固定できます。
Read-onlyを解除してSubmoduleを編集する手順
Visual Studio 18.9では、Submoduleは既定でRead-onlyとして扱われます。共有ライブラリやSDKを参照するだけの開発者が、誤ってSubmodule側へ変更をコミットするのを防ぐためです。(Microsoft for Developers)
Submodule内のコードを編集する場合は、次の手順で設定を変更します。
Read-only解除の設定
- Visual Studio 18.9以降で対象のソリューションまたはフォルダーを開きます。
- メニューバーから
Toolsを選択します。 Optionsを開きます。Source Control→Gitへ進みます。Automatically activate multiple repositoriesを探します。- 値を
Yes, include submodulesへ変更します。 - 設定を保存します。
- ソリューションを閉じて、もう一度開きます。
Microsoftのリリースノートでは、Submoduleを編集する場合にYes, include submodulesを選択するよう案内されています。また、複数リポジトリの自動有効化設定は、変更後にソリューションを読み込み直すまで反映されない場合があります。(Microsoft Learn)
Git Repositoryウィンドウを開く
Submoduleの管理画面は、次のいずれかの方法で開けます。
View→Git Repositoryを選択するCtrl+0に続けてCtrl+Rを押す- Visual Studioの検索から
Git Repositoryを検索する
Git Repositoryウィンドウを開くと、左側にSubmodulesセクションが表示されます。(Microsoft Learn)
Read-onlyを解除すべきケース
次のような開発者は、Submoduleを編集可能にするメリットがあります。
- 親アプリと共有ライブラリを同時に修正する
- Submodule側の不具合をデバッグして修正する
- Submodule側でブランチを作成してPull Requestを送る
- 親リポジトリと子リポジトリの変更を同じVisual Studioで確認する
一方、Submoduleをビルド依存先として利用するだけなら、Read-onlyのままにしておく方が安全です。
Yes, include submodulesを設定すると、Visual Studioが複数のリポジトリを有効化するため、リポジトリ数によっては解析や状態確認に使うリソースが増える可能性があります。Submoduleを編集しない利用者まで一律に有効化するのではなく、担当者ごとに設定する運用が適しています。(Microsoft Learn)
Visual StudioからGit Submoduleを追加する方法
Visual Studio 18.9では、Git RepositoryウィンドウのSubmodulesセクションからSubmoduleを追加できます。
追加前に決めておく項目
操作を始める前に、次の情報を確認します。
| 確認項目 | 具体例 |
|---|---|
| 取得元リポジトリ | GitHubやAzure DevOps上の共有ライブラリ |
| 配置先の相対パス | shared/CommonLibrary |
| 認証方法 | Git Credential Manager、組織アカウントなど |
| 利用者のアクセス権 | 開発PCとCIの両方から取得できるか |
| 採用するコミット | 動作確認済みのタグまたはコミット |
特に重要なのがアクセス権です。親リポジトリを取得できても、非公開のSubmoduleに対する権限がなければ、Submoduleの初期化や更新は失敗します。
Submoduleを追加する流れ
- リポジトリピッカーで親リポジトリを選択します。
Git RepositoryウィンドウのSubmodulesセクションを開きます。- Submoduleの追加操作を選択します。
- 取得元のリポジトリURLを指定します。
- 親リポジトリ内の配置先パスを指定します。
- 追加後、
Git Changesウィンドウを確認します。 .gitmodulesとSubmoduleのエントリを親リポジトリへコミットします。- 親リポジトリをPushします。
Gitのコマンドラインでは、次の操作に相当します。
git submodule add <repository-url> <path>
Git Submoduleを追加すると、取得元URLなどが.gitmodulesへ記録され、親リポジトリにはSubmoduleのコミットを示すエントリが追加されます。(Git)
追加後に確認すること
追加操作が完了したら、別のフォルダーへ親リポジトリを新規クローンし、Submoduleを正しく取得できるか確認します。
確認すべきポイントは次のとおりです。
.gitmodulesが親リポジトリへコミットされている- Submoduleのパスに誤りがない
- 他の開発者がSubmoduleへアクセスできる
- CIサービスにSubmoduleの認証情報が設定されている
- ビルド時にSubmoduleが初期化される
自分のPCですでにSubmoduleが取得済みだと、設定漏れに気付きにくくなります。新規クローンによる検証を完了条件にするのが安全です。
Submoduleを更新するときの正しい考え方
Submoduleの「更新」には、異なる意味が含まれます。
親リポジトリが指定するコミットへ合わせる
一般的なgit submodule updateは、Submoduleを親リポジトリに記録されたコミットへ合わせる操作です。
git submodule update --init --recursive
このコマンドは、未初期化のSubmoduleを初期化し、親リポジトリが要求するコミットをチェックアウトします。入れ子になったSubmoduleも処理したい場合は、--recursiveを使用します。(Git)
Submoduleの新しいバージョンを親へ取り込む
共有ライブラリの新しいコミットを親プロジェクトへ採用するときは、次の順番で操作します。
- リポジトリピッカーでSubmoduleを選択します。
- Submodule側で目的のブランチまたはコミットをチェックアウトします。
- 必要に応じてSubmodule内のコードを修正します。
- Submodule側でコミットします。
- Submodule側のリモートリポジトリへPushします。
- リポジトリピッカーで親リポジトリへ戻ります。
Git ChangesでSubmoduleの参照先変更を確認します。- 親リポジトリ側でも変更をコミットします。
- 親リポジトリをPushします。
重要なのは、Submodule側を先にPushし、親リポジトリを後からPushすることです。
親リポジトリだけを先にPushすると、他の開発者やCIが、まだリモートに存在しないSubmoduleのコミットを取得しようとして失敗します。Gitには、Submodule側のコミットがリモートへ公開されているかを確認する仕組みもあります。(Git)
「Update」が常に最新ブランチを取得するとは限らない
Visual Studioの公式発表では、Submodulesセクションから更新できることは示されていますが、すべての更新オプションについて詳細には説明されていません。
Git標準のgit submodule updateは、通常、親リポジトリに記録されたコミットへSubmoduleを合わせます。一方、Submoduleのリモート追跡ブランチを基準に更新する--remoteは別の動作です。(Git)
そのため、Visual Studio上の更新操作を、無条件に「Submoduleの既定ブランチを最新版へ進める機能」と解釈しないことが重要です。実際のプロジェクトへ導入する前に、テスト用ブランチで次の点を確認してください。
- 更新後にチェックアウトされたコミットID
- 親リポジトリに記録されているコミットID
- Submoduleの現在のブランチ
Git Changesへ表示される差分- 入れ子になったSubmoduleの扱い
Submoduleを削除する手順
Visual Studio 18.9では、Git RepositoryウィンドウからSubmoduleを削除できます。
削除前の確認
削除操作の前に、Submodule側へ未コミットの変更がないか確認します。
git status
未コミットの変更がある状態で削除すると、作業内容を失う可能性があります。必要な変更は、Submodule側でコミットまたは退避してから操作してください。
Visual Studioで削除する流れ
- リポジトリピッカーで親リポジトリを選択します。
Git RepositoryウィンドウのSubmodulesセクションを開きます。- 削除するSubmoduleを選択します。
- 削除またはRemoveに相当する操作を実行します。
Git Changesウィンドウで変更内容を確認します。.gitmodulesから対象設定が削除されていることを確認します。- Submoduleのパスが削除対象になっていることを確認します。
- 親リポジトリへコミットしてPushします。
この操作で削除されるのは、親リポジトリから見たSubmoduleの参照です。GitHubやAzure DevOpsにあるSubmoduleのリモートリポジトリ自体が削除されるわけではありません。
Gitでは、Submoduleを削除すると親リポジトリのgitlinkと.gitmodules内の設定が削除されます。一方、過去のコミットを再チェックアウトできるように、ローカルの.git/modules配下へGitデータが残る場合があります。これは削除失敗ではありません。(Git)
削除とdeinitの違い
Submoduleをプロジェクトから完全に外すのではなく、ローカルPC上で一時的に展開を解除したいだけなら、削除ではなくdeinitを使う方法があります。
git submodule deinit <path>
| 操作 | 用途 | 親リポジトリへの影響 |
|---|---|---|
| deinit | ローカルの作業ツリーを一時的に解除 | 親リポジトリの履歴は変更しない |
| Remove/Delete | プロジェクトからSubmoduleを外す | .gitmodulesや参照先の変更をコミットする |
| リモートリポジトリ削除 | Submoduleの保管先自体を削除 | Gitホスティング側で別途操作する |
一時的にSubmoduleを使わないだけなのか、プロジェクトから正式に削除するのかを区別して操作してください。(Git)
Submodule内の変更をコミットするときの注意点
Visual StudioでSubmoduleを編集可能にした後は、現在選択しているリポジトリを常に確認してください。
Git Changesウィンドウでは、親リポジトリとSubmoduleの変更がリポジトリごとに管理されます。複数リポジトリ対応では、それぞれのリポジトリを切り替えながら、ステージやコミットを実行できます。(Microsoft Learn)
安全なコミット順序は次のとおりです。
| 順番 | 対象 | 操作 |
|---|---|---|
| 1 | Submodule | ブランチを確認 |
| 2 | Submodule | ファイルを編集 |
| 3 | Submodule | コミット |
| 4 | Submodule | Push |
| 5 | 親リポジトリ | Submoduleの参照先変更を確認 |
| 6 | 親リポジトリ | 参照先変更をコミット |
| 7 | 親リポジトリ | Push |
detached HEADのまま編集しない
Git Submoduleを親リポジトリに記録されたコミットへ更新すると、Submoduleがdetached HEADになる場合があります。Git標準のチェックアウト方式では、この状態が既定の動作です。(Git)
detached HEADのままコミットすると、後からコミットを見失いやすくなります。Submoduleを修正するときは、リポジトリピッカーで対象Submoduleを選び、作業用ブランチをチェックアウトしてから編集してください。
確認には、Visual Studioのブランチピッカーか、次のコマンドを利用できます。
git branch --show-current
何も表示されない場合は、detached HEADになっている可能性があります。
よくある問題と解決方法
| 症状 | 主な原因 | 対処方法 |
|---|---|---|
Submodulesセクションが表示されない | Visual Studioが18.9未満 | Visual Studio Installerから18.9以降へ更新する |
| Submoduleが検出されない | 親リポジトリではなく子フォルダーだけを開いている | .gitmodulesを含む親のソリューションまたはフォルダーを開く |
| Submodule内を編集できない | 既定のRead-only | Automatically activate multiple repositoriesをYes, include submodulesへ変更する |
| 設定を変えても反映されない | ソリューションが再読み込みされていない | ソリューションまたはVisual Studioを開き直す |
| 親リポジトリにSubmoduleの変更が表示される | 子リポジトリのコミットIDが変わった | 正常な動作。参照先変更として親側でもコミットする |
| 他のPCでSubmoduleを取得できない | .gitmodules未コミット、権限不足、初期化漏れ | 新規クローン環境でアクセス権と初期化処理を確認する |
| CIでビルド対象ファイルが見つからない | CIがSubmoduleを取得していない | checkout設定でSubmoduleを有効化するか、git submodule update --init --recursiveを実行する |
| 親を取得するとSubmoduleがdetached HEADになる | 親が特定コミットを参照している | 編集前にSubmodule側の作業ブランチをチェックアウトする |
削除後も.git/modulesにデータが残る | 過去コミットの再現用データが保持されている | 容量上の問題がなければ、そのままでもよい |
チーム開発で決めておきたい運用ルール
Visual StudioでSubmoduleを操作しやすくなっても、親と子が別々のリポジトリである点は変わりません。次のルールを決めておくと、参照切れやコミット漏れを防げます。
利用者と保守担当者で設定を分ける
Submoduleを参照するだけの開発者は、既定のRead-onlyを維持します。
Submoduleを修正する保守担当者だけが、Yes, include submodulesを有効化します。誤コミットの防止とVisual Studioの負荷軽減を両立できます。
Submodule変更は2段階でレビューする
Submodule側のコード変更と、親リポジトリ側の参照先変更は、別々のPull Requestに分けると確認しやすくなります。
推奨する流れは次のとおりです。
- Submodule側で修正Pull Requestを作成する。
- Submodule側をマージしてコミットIDを確定する。
- 親リポジトリで参照先を更新する。
- 親リポジトリ側でもPull Requestを作成する。
- 親アプリのビルドとテストを実行する。
親側のPull Requestには、採用するSubmoduleのコミットIDやリリース番号を記載しておくと追跡しやすくなります。
CIでは新規取得を前提に検証する
開発PCではSubmoduleがすでに展開されているため、認証や初期化処理の問題が表面化しないことがあります。
CIでは、毎回クリーンな状態から次の処理を確認します。
git submodule sync --recursive
git submodule update --init --recursive
非公開Submoduleを利用している場合は、親リポジトリだけでなく、Submoduleへアクセスするための認証情報も必要です。
複雑な操作ではコマンドラインも残しておく
Visual Studio 18.9のSubmodule対応は、Microsoftが「最初のマイルストーン」と位置付けている機能です。追加・更新・削除などの日常操作はIDE内で行えますが、特殊な更新方式、入れ子構成、URL変更、全Submoduleへの一括処理などでは、Gitコマンドが必要になる可能性があります。(Microsoft Learn)
障害対応用として、少なくとも次のコマンドはチーム内で共有しておくと安心です。
git submodule status
git submodule sync --recursive
git submodule update --init --recursive
git submodule foreach 'git status'
Git Submoduleを採用するか判断する基準
Visual Studioで管理しやすくなったとしても、すべての共有コードをSubmoduleにする必要はありません。
Submoduleが向いているケース
- 共有コードをソースのままデバッグしたい
- 親プロジェクトごとに利用するコミットを固定したい
- 子プロジェクトの履歴やアクセス権を分離したい
- 親と子を別々のリポジトリとして保守したい
- 特定バージョンのSDKやビルドスクリプトを組み込みたい
別の方法を検討した方がよいケース
- ライブラリを通常の依存パッケージとして配布できる
- 利用者がライブラリのソースを直接編集する必要がない
- 多数の入れ子SubmoduleによってCIが複雑になる
- 親と子を常に同じタイミングで変更する
- 開発者がGit Submoduleの参照構造を理解していない
.NETライブラリであれば、安定版をNuGetパッケージとして配布し、ライブラリの共同開発が必要な場面だけSubmoduleを使う方法もあります。
Visual Studio 18.9で安全にSubmoduleを運用するポイント
Visual Studio 18.9では、Git RepositoryウィンドウからSubmoduleの追加・更新・削除を行えるため、日常的な管理作業をIDE内で完結しやすくなりました。
まずはVisual Studioを18.9以降へ更新し、Git RepositoryウィンドウにSubmodulesセクションが表示されることを確認してください。
Submoduleを参照するだけならRead-onlyを維持します。内部を修正する担当者は、Automatically activate multiple repositoriesをYes, include submodulesへ変更し、ソリューションを再読み込みします。
変更を公開するときは、Submodule側を先にコミット・Pushし、その後に親リポジトリの参照先変更をコミット・Pushします。最後に、新規クローン環境やCIでSubmoduleを正しく取得できることまで確認すれば、参照切れを防ぎながらVisual Studio 18.9の新しい管理機能を活用できます。

コメント