Submodule Commands
Ivaldi VCS supports Git-style submodules with enhanced features like timeline-awareness and automatic Git conversion.
Overview
Submodules allow you to include external repositories within your main repository. Ivaldiβs submodule system:
- Automatically converts Git submodules when cloning or initializing
- Uses BLAKE3 hashes internally for Ivaldi-native submodules
- Maintains Git SHA-1 mapping for GitHub compatibility
- Tracks submodules per timeline (not just per branch)
- Auto-shelves submodule changes when switching timelines
Automatic Git Submodule Conversion
When you clone a Git repository with submodules or run ivaldi forge in a Git repository with submodules, Ivaldi automatically:
- Detects
.gitmodulesfile - Clones missing submodules
- Converts Git objects to Ivaldi format
- Creates
.ivaldimodulesconfiguration - Stores dual-hash mapping (BLAKE3 β Git SHA-1)
Example: Clone with Submodules
$ ivaldi download https://github.com/owner/repo-with-submodules
Cloning repository from GitHub...
β Cloned main repository
Converting Git repository to Ivaldi format...
β Converted 1,234 Git objects
π¦ Detected Git submodules...
Submodule 'external-lib' at libs/external-lib
Cloning from https://github.com/owner/external-lib...
β Cloned (commit: abc123)
Converting to Ivaldi format...
β Converted 456 objects
β Initialized 2 submodules
β Created .ivaldimodules
Repository ready! Current timeline: main
Example: Initialize in Git Repo with Submodules
$ cd my-git-repo-with-submodules
$ ivaldi forge
Ivaldi repository initialized
Detecting existing Git repository...
β Converted 2,345 Git objects
π¦ Detected Git submodules...
Found 3 submodules in .gitmodules
Submodule 'lib1' at libs/lib1 (commit: 789abc)
β Converted to Ivaldi format
β Converted 3 Git submodules
β Created .ivaldimodules
Configuration File: .ivaldimodules
Ivaldi uses .ivaldimodules (similar to Gitβs .gitmodules) to track submodule configuration.
Format
# .ivaldimodules - Ivaldi Submodule Configuration
# Version: 1
[submodule "library-name"]
path = libs/external-lib
url = https://github.com/owner/external-lib
timeline = main
commit = 1a2b3c4d5e6f... # BLAKE3 hash (64 hex chars)
git-commit = abc123def... # Git SHA-1 (40 hex chars, optional)
shallow = true # Optional
freeze = false # Optional
Fields
- path (required): Relative path in repository
- url (required): Repository URL (https, ssh, file)
- timeline (required): Timeline name to track
- commit (required): BLAKE3 hash of target commit (PRIMARY reference)
- git-commit (optional): Git SHA-1 for GitHub sync only
- shallow (optional): Use shallow clone
- freeze (optional): Prevent automatic updates
- ignore (optional): How to handle uncommitted changes in status
Disabling Automatic Submodule Cloning
Use the --recurse-submodules=false flag to skip submodule initialization:
$ ivaldi download https://github.com/owner/repo --recurse-submodules=false
# Or
$ ivaldi forge --recurse-submodules=false
Internal Architecture
Storage
Ivaldi stores submodules using native mechanisms:
.ivaldi/
βββ modules/
β βββ metadata.db # BoltDB: per-timeline state
β βββ external-lib/.ivaldi/ # Full Ivaldi repo for submodule
β βββ vendor-tool/.ivaldi/ # Another submodule
βββ objects/ # SubmoduleNode objects in CAS
βββ ...
Node Types
SubmoduleNode (stored in CAS):
- URL, Path, Timeline
- CommitHash (BLAKE3) - primary reference
- Flags (shallow, freeze)
HAMT Entry:
- Name, Type (SubmoduleEntry)
- SubmoduleRef with BLAKE3 hashes
Dual-Hash Mapping
BoltDB bucket git-submodule-mappings:
Key: "ivaldi-commit-" + blake3_hex
Value: git_sha1
Key: "git-commit-" + git_sha1
Value: blake3_hex
Git Compatibility
Push to GitHub
When pushing to GitHub, Ivaldi:
- Converts
.ivaldimodulesβ.gitmodules - Maps BLAKE3 β Git SHA-1 using dual-hash mapping
- Creates Git gitlink entries (mode 160000)
- Pushes submodule references
Pull from GitHub
When pulling from GitHub, Ivaldi:
- Parses
.gitmodules - Converts gitlink entries to SubmoduleNodes
- Maps Git SHA-1 β BLAKE3
- Creates/updates
.ivaldimodules
Differences from Git Submodules
| Feature | Git | Ivaldi |
|---|---|---|
| Internal reference | Git SHA-1 | BLAKE3 hash |
| Configuration | .gitmodules |
.ivaldimodules |
| Branch tracking | Git branches | Ivaldi timelines |
| Auto-shelving | Manual (git stash) |
Automatic |
| GitHub push | Native | Converts to Git format |
| Missing submodules | Error | Auto-clone during forge |
Examples
Clone Repo with Nested Submodules
$ ivaldi download https://github.com/owner/repo
# Automatically handles recursive submodules (depth limit: 10)
Disable Submodule Cloning
$ ivaldi download https://github.com/owner/repo --recurse-submodules=false
# Clone parent only, skip submodules
Check Submodule Commit References
$ cat .ivaldimodules
[submodule "lib"]
path = libs/external
url = https://github.com/owner/lib
timeline = main
commit = 1a2b3c4d5e6f7890... # BLAKE3 (source of truth)
git-commit = abc123def456... # Git SHA-1 (for GitHub sync)
Troubleshooting
Missing Submodule Directories
If .ivaldimodules exists but submodule directories are missing:
# Will be auto-cloned on next forge
$ ivaldi forge
Submodule URL Changed
If submodule URL was updated in remote .ivaldimodules:
# Manual update (future command)
$ ivaldi submodule sync
Circular Dependencies
Ivaldi detects circular submodule references:
Error: Circular submodule reference detected: A β B β A
Future Commands
The following submodule commands are planned for future versions:
ivaldi submodule add <url> [path] # Add submodule
ivaldi submodule init [paths...] # Initialize submodules
ivaldi submodule update [--remote] # Update to latest/specific commit
ivaldi submodule status # Show submodule status
ivaldi submodule remove <path> # Remove submodule
ivaldi submodule sync # Sync URLs from .ivaldimodules