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
gitoxidefor high-performance git operations - Robust fallbacks - Automatic fallback to
git2and 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 submodMise 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@latestgit 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 branchignore: 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 checkInitialize all missing submodules:
submod initUpdate all submodules to their latest commits:
submod updateHard reset submodules (stash changes, reset --hard, clean):
# Reset all submodules submod reset --all # Reset specific submodules submod reset my-lib vendor-utilsRun 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 releaseThis 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 ciThe 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 testssubmod/ βββ 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 ciorhk run cibefore 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 checkSparse checkout not working:
- Ensure paths in
sparse_pathsare relative to the submodule root - Check that the submodule repository contains the specified paths
- Verify sparse checkout is enabled:
git config core.sparseCheckoutin 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
gitoxidefor 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