Overview
Git submodules allow you to keep a Git repository as a subdirectory of another Git repository. This lets you clone another repository into your project and keep your commits separate.Nested Repositories
Include external repositories within your project
Version Pinning
Lock submodules to specific commits
Automatic Updates
GitHub Desktop handles submodule updates automatically
Recursive Operations
Clone, pull, and checkout operations include submodules
Understanding Submodules
What are Submodules?
Submodules are Git repositories embedded inside another Git repository:When to Use Submodules
Good Use Cases:External Dependencies
Include libraries or frameworks as source
Shared Code
Share common code between projects
Monorepo Components
Manage separate components with independent histories
Version Control
Pin dependencies to specific versions
- Package managers (npm, pip, Maven) for dependencies
- Mono-repo tools (Lerna, Nx) for related projects
- Git subtrees for simpler embedding
Submodule Configuration
.gitmodules File
Submodules are defined in.gitmodules:
.gitmodules
path: Location in your repositoryurl: Remote repository URLbranch: (Optional) Branch to track
.git/config
Local configuration in.git/config:
Cloning with Submodules
GitHub Desktop automatically handles submodules when cloning:Automatic Recursive Clone
When you clone a repository in GitHub Desktop, it automatically clones all submodules recursively using the
--recursive flag.What Happens:
Updating Submodules
GitHub Desktop automatically updates submodules during Git operations:Update Implementation
When Submodules Update:
GitHub Desktop updates submodules after:- Checkout: Switching branches
- Pull: Pulling changes from remote
- Merge: Merging branches
- Rebase: Rebasing branches
Progress Tracking
GitHub Desktop shows progress when updating submodules, with a smooth exponential curve since the total count isn’t known upfront.
Viewing Submodule Status
GitHub Desktop detects submodules and their state:Listing Submodules
Submodule Status Indicators
The first character ingit submodule status output indicates:
(space): Submodule is checked out at the correct commit-: Submodule is not initialized+: Submodule is checked out to a different commit than recordedU: Submodule has merge conflicts
Modifying Submodules
Updating a Submodule
To update a submodule to a newer commit:Resetting Submodules
Reset submodules to the recorded commit:- Discard local changes in submodules
- Reset to the commit recorded in parent
- Fix submodules in unexpected states
Submodule Workflows
Adding a New Submodule
Use the terminal:Removing a Submodule
Use the terminal:Updating All Submodules
Update all submodules to their latest commits:File Protocol Support
Some operations allow file:// URLs for submodules:- Local submodules (for testing)
- Submodules on network drives
- Internal corporate repositories
Nested Submodules
GitHub Desktop supports submodules within submodules:--recursive flag ensures all levels are:
- Cloned when cloning the parent
- Updated when updating the parent
- Initialized when checking out
Best Practices
-
Keep Submodules Updated
- Regularly update to latest commits
- Test after updating
- Commit submodule updates separately
-
Document Submodule Purpose
- Add comments in
.gitmodules - Document in README
- Explain why it’s a submodule
- Add comments in
-
Avoid Modifying Submodules Directly
- Make changes in the submodule’s repository
- Pull updates into parent repo
- Don’t commit directly in submodule directories
-
Use HTTPS for Public Submodules
- SSH URLs require key access
- HTTPS works for everyone
- Easier for CI/CD
-
Initialize Before Operations
- Always run
git submodule update --init - GitHub Desktop does this automatically
- Important for CI/CD scripts
- Always run
-
Consider Alternatives
- Package managers for dependencies
- Monorepo tools for related code
- Subtrees for simpler workflows
Common Issues
Submodule Not Updating
Submodule Not Updating
If a submodule doesn’t update:
- Check if it’s initialized:
git submodule status - Update manually:
git submodule update --init --recursive - Verify URL in
.gitmodulesis correct - Check network/authentication issues
Submodule Showing as Modified
Submodule Showing as Modified
If submodule always appears modified:
- Submodule is at a different commit than recorded
- Check current commit:
cd submodule && git rev-parse HEAD - Reset to recorded:
git submodule update --force - Or commit the new state to update the pointer
Detached HEAD in Submodule
Detached HEAD in Submodule
Submodules are typically in detached HEAD state:
- This is normal behavior
- Submodules point to specific commits, not branches
- To make changes:
Clone Without Submodules
Clone Without Submodules
If submodules are missing after clone:
- Initialize them:
git submodule init - Update them:
git submodule update --recursive - Or in one command:
git submodule update --init --recursive - GitHub Desktop does this automatically
Authentication Failures
Authentication Failures
If submodule operations fail with auth errors:
- Verify you have access to submodule repository
- Check URL protocol (HTTPS vs SSH)
- Ensure credentials are configured
- Try updating URL in
.gitmodules
Submodule Alternatives
Git Subtrees
Pros:- Simpler than submodules
- No special commands needed
- Easier for collaborators
- History becomes intermingled
- Harder to contribute back upstream
Package Managers
Pros:- Designed for dependencies
- Version resolution
- Easier updates
- Requires package to be published
- Less control over source
Monorepo Tools
Pros:- Better tooling (Lerna, Nx, Rush)
- Shared dependencies
- Atomic commits across projects
- Repository can get large
- Requires tool adoption