submod
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.
🚀 Features
- 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
📋 Table of Contents
🔧 Installation
Using Cargo
Using Mise
Mise is a project management tool and package manager that can manage your development environment.
# Global installation
# Project-specific installation
From Source
🚀 Quick Start
-
Initialize a config file in your git repository:
# Create a basic submod.toml configuration -
Initialize your submodules:
-
Check status:
⚙️ Configuration
Create a submod.toml file in your repository root:
# Global defaults applied to all submodules
[]
= "dirty" # ignore dirty state in status
= "checkout" # update method
= "main" # default branch to track
# Individual submodule configuration
[]
= "vendor/utils"
= "https://github.com/example/utils.git"
= ["src/", "include/", "*.md"]
= "all" # override default ignore setting
= true # whether submodule is active
[]
= "libs/my-submodule"
= "https://github.com/example/my-submodule.git"
= ["src/core/", "docs/"]
= "develop" # track specific branch
Configuration Options
Global Defaults
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)
Per-Submodule Settings
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
📖 Commands
submod add
Add a new submodule to your configuration and repository:
submod check
Check the status of all configured submodules:
submod init
Initialize all missing submodules:
submod update
Update all submodules to their latest commits:
submod reset
Hard reset submodules (stash changes, reset --hard, clean):
# Reset all submodules
# Reset specific submodules
submod sync
Run a complete sync (check + init + update):
💻 Usage Examples
Basic Workflow
# Start with checking current state
# Initialize any missing submodules
# Update everything to latest
# Or do it all at once
Adding Submodules with Sparse Checkout
# Add a submodule that only checks out specific directories
Working with Different Configurations
# Use a custom config file
# Check status with custom config
Handling Problematic Submodules
# Reset a problematic submodule
# Check what's wrong
# Re-sync everything
🛠️ Development
Prerequisites
- Rust 1.87 or later
- Git
- Mise (recommended) - for tool management and task running
Quick Setup with Mise (Recommended)
# Clone the repository
# Install mise if you haven't already
|
# Install all development tools and dependencies
# Build the project
# or: mise run b (alias)
# Run tests
# Run the full CI suite (build + lint + test)
Available Mise Tasks
# Build the project
# Run tests
# Lint with clippy
# Run full CI pipeline
# Clean build artifacts
# Cut a new release (maintainers only)
Git Hooks with hk
This project uses hk for automated git hooks that ensure code quality:
# Install git hooks (done automatically with mise install)
# Run pre-commit checks manually
# Run all linters and checks
# Auto-fix issues where possible
# Run CI checks locally
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
Manual Setup (Alternative)
If you prefer not to use mise:
# Clone the repository
# Install Rust if needed
|
# Build the project
# Run tests
# or hk run test
# Or use the comprehensive test runner
Running Tests
# Using mise (recommended)
# Using hk
# Using cargo directly
# Using the test script
Project Structure
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
🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
Quick Contributing Steps
- 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
Development Guidelines
- 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
🔍 Troubleshooting
Common Issues
Submodule not initializing:
# Check if the URL is accessible
# Verify your configuration
Sparse 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
📋 Motivation
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.
📄 License
This project is licensed under the Plain MIT License.
🙏 Acknowledgments
- 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