A lightweight, fast CLI tool for managing git submodules with advanced sparse checkout support. Built on top of gitoxide
and git2
libraries for maximum performance and reliability.
- TOML-based configuration - Define submodules, sparse-checkout paths, and settings in a simple config file
- Global defaults with overrides - Set project-wide submodule settings with per-submodule customization
- Sparse checkout support - Efficiently checkout only the parts of submodules you need
- Fast operations - Leverages
gitoxide
for high-performance git operations - Robust fallbacks - Automatic fallback to
git2
and CLI when needed - Comprehensive commands - Add, check, init, update, reset, and sync submodules with ease
- Developer-friendly - Clear status reporting and error messages
cargo install submod
Mise is a project management tool and package manager that can manage your development environment.
# Global installation
mise use -g cargo:submod@latest
# Project-specific installation
mise use cargo:submod@latest
git clone https://github.com/yourusername/submod.git
cd submod
cargo install --path .
-
Initialize a config file in your git repository:
# Create a basic submod.toml configuration cat > submod.toml << EOF [defaults] ignore = "dirty" [my-submodule] path = "vendor/my-lib" url = "https://github.com/example/my-lib.git" sparse_paths = ["src/", "include/", "*.md"] EOF
-
Initialize your submodules:
submod init
-
Check status:
submod check
Create a submod.toml
file in your repository root:
# Global defaults applied to all submodules
[defaults]
ignore = "dirty" # ignore dirty state in status
update = "checkout" # update method
branch = "main" # default branch to track
# Individual submodule configuration
[vendor-utils]
path = "vendor/utils"
url = "https://github.com/example/utils.git"
sparse_paths = ["src/", "include/", "*.md"]
ignore = "all" # override default ignore setting
active = true # whether submodule is active
[my-submodule]
path = "libs/my-submodule"
url = "https://github.com/example/my-submodule.git"
sparse_paths = ["src/core/", "docs/"]
branch = "develop" # track specific branch
ignore
: How to handle dirty submodules (all
,dirty
,untracked
,none
)update
: Update strategy (checkout
,rebase
,merge
,none
,!command
)branch
: Default branch to track (.
for current superproject branch)fetchRecurse
: Fetch recursion (always
,on-demand
,never
)
path
: Local path where submodule should be placedurl
: Git repository URLsparse_paths
: Array of paths to include in sparse checkoutactive
: Whether the submodule is active (default:true
)- All global defaults can be overridden per submodule
Add a new submodule to your configuration and repository:
submod add my-lib libs/my-lib https://github.com/example/my-lib.git \
--sparse-paths "src/,include/" \
--settings "ignore=all"
Check the status of all configured submodules:
submod check
Initialize all missing submodules:
submod init
Update all submodules to their latest commits:
submod update
Hard reset submodules (stash changes, reset --hard, clean):
# Reset all submodules
submod reset --all
# Reset specific submodules
submod reset my-lib vendor-utils
Run a complete sync (check + init + update):
submod sync
# Start with checking current state
submod check
# Initialize any missing submodules
submod init
# Update everything to latest
submod update
# Or do it all at once
submod sync
# Add a submodule that only checks out specific directories
submod add react-components src/components https://github.com/company/react-components.git \
--sparse-paths "src/Button/,src/Input/,README.md"
# Use a custom config file
submod --config my-custom.toml check
# Check status with custom config
submod --config production.toml sync
# Reset a problematic submodule
submod reset my-problematic-submodule
# Check what's wrong
submod check
# Re-sync everything
submod sync
- Rust 1.87 or later
- Git
- Mise (recommended) - for tool management and task running
# Clone the repository
git clone https://github.com/bashandbone/submod.git
cd submod
# Install mise if you haven't already
curl https://mise.run | sh
# Install all development tools and dependencies
mise install
# Build the project
mise run build
# or: mise run b (alias)
# Run tests
mise run test
# Run the full CI suite (build + lint + test)
mise run ci
# Build the project
mise run build # or: mise run b
# Run tests
mise run test
# Lint with clippy
mise run lint
# Run full CI pipeline
mise run ci
# Clean build artifacts
mise run clean
# Cut a new release (maintainers only)
mise run release
This project uses hk for automated git hooks that ensure code quality:
# Install git hooks (done automatically with mise install)
hk install
# Run pre-commit checks manually
hk run pre-commit
# Run all linters and checks
hk check
# Auto-fix issues where possible
hk fix
# Run CI checks locally
hk run ci
The pre-commit hooks automatically run:
- cargo fmt - Code formatting
- cargo clippy - Linting
- cargo test - Test suite
- typos - Spell checking
- prettier - TOML/YAML formatting
- cargo deny - Security and license auditing
If you prefer not to use mise:
# Clone the repository
git clone https://github.com/bashandbone/submod.git
cd submod
# Install Rust if needed
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Build the project
cargo build
# Run tests
cargo test
# or hk run test
# Or use the comprehensive test runner
./scripts/run-tests.sh --verbose
# Using mise (recommended)
mise run test # Run all tests
mise run ci # Run full CI suite
# Using hk
hk run test # Run tests only
hk run ci # Run CI checks
# Using cargo directly
cargo test # Run all tests
cargo test --test integration_tests # Integration tests only
# Using the test script
./scripts/run-tests.sh --verbose # Comprehensive reporting
./scripts/run-tests.sh --performance # Include performance tests
./scripts/run-tests.sh --filter sparse_checkout # Filter tests
submod/
βββ src/
β βββ main.rs # CLI entry point
β βββ commands.rs # Command definitions
β βββ config.rs # TOML configuration handling
β βββ gitoxide_manager.rs # Core submodule operations
βββ tests/ # Integration tests
βββ sample_config/ # Example configurations
βββ scripts/ # Development scripts
βββ docs/ # Documentation
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature
- Set up development environment:
mise install
(installs all tools and git hooks) - Make your changes and add tests if applicable
- Commit your changes:
git commit -m 'Add amazing feature'
(hooks run automatically) - Push to your branch:
git push origin feature/amazing-feature
(they'll actually run again in check mode, so they need to pass) - Open a Pull Request
- Follow Rust best practices and idioms
- Add tests for new functionality. I'm not big on unit tests, but integration tests are essential.
- Update documentation for user-facing changes
- Use conventional commit messages
- Run
mise run ci
orhk run ci
before submitting PR - Pre-commit hooks will automatically format code and run basic checks
- All automated checks must pass before PR can be merged
Submodule not initializing:
# Check if the URL is accessible
git ls-remote <submodule-url>
# Verify your configuration
submod check
Sparse checkout not working:
- Ensure paths in
sparse_paths
are relative to the submodule root - Check that the submodule repository contains the specified paths
- Verify sparse checkout is enabled:
git config core.sparseCheckout
in the submodule
Permission issues:
- Ensure you have proper SSH keys set up for private repositories
- Check if your Git credentials are configured correctly
Managing git submodules, especially with sparse checkouts, can be complex and error-prone. Traditional git submodule commands require multiple steps and careful attention to configuration details.
This tool was created to:
- Reduce barriers to contribution - Make it easier for new developers to work with projects using submodules
- Simplify complex workflows - Handle initialization, updates, and sparse checkout configuration automatically
- Provide better tooling - Clear status reporting and error messages
- Leverage modern Git libraries - Use
gitoxide
for better performance and reliability
The tool is actively used in multiple projects at @knitli and @plainlicense, where submodules are essential for sharing core functionality across repositories.
This project is licensed under the Plain MIT License.
- gitoxide - Fast and safe pure Rust implementation of Git
- git2-rs - Rust bindings to libgit2
- clap - Command line argument parser
Homepage β’ Documentation β’ Crate
Made with β€οΈ for the Rust and Git communities