/git-submodule-commit-all - Bottom-Up Submodule Commit & Push
Bottom-up commit and push across all dirty submodules, update parent pointers, and run recursive init.
Usage
/git-submodule-commit-all # Full workflow: commit, push, init
/git-submodule-commit-all --dry-run # Preview what would be committed
/git-submodule-commit-all --init-only # Skip commits, just run recursive init
/git-submodule-commit-all --fix-orphans # Also detect and fix orphaned entries
Options
| Option | Description |
|---|---|
--dry-run | Show dirty submodules and changes without committing |
--init-only | Only run git submodule update --init --recursive |
--fix-orphans | Detect and fix orphaned submodule entries |
--no-push | Commit but don't push |
--no-init | Skip recursive init after committing |
System Prompt
EXECUTION DIRECTIVE:
When the user invokes /git-submodule-commit-all, execute this 6-step workflow:
Step 1: Discover Dirty Submodules
# Find submodules with new commits (pointer updates needed)
git submodule status 2>&1 | grep '^\+'
# Find submodules with modified/untracked content
git status --short | grep '^ [mM]'
Categorize each submodule:
- New commits (
+prefix ingit submodule status) - needs pointer update in parent - Modified content - has uncommitted changes inside the submodule working tree
- Untracked content - has untracked files inside
If --dry-run, display the list and stop.
Step 2: Commit & Push Each Dirty Submodule (Bottom-Up)
For each submodule with new commits or modified content:
REPO="path/to/submodule"
# Ensure on main branch
git -C "$REPO" checkout main 2>/dev/null
# Check for uncommitted changes
git -C "$REPO" status --short
# If changes exist, stage and commit
git -C "$REPO" add -A
git -C "$REPO" commit -m "chore: <describe changes>"
# Push to remote
git -C "$REPO" push
Commit message generation: Inspect git -C "$REPO" diff --cached --stat to generate a descriptive message.
Handle index.lock: If fatal: Unable to create index.lock, kill the holding process and remove the lock file.
Step 3: Stage Submodule Pointer Updates in Parent
# Add all submodules with new commits
git add submodules/path/to/each/dirty/submodule
# Also add any directly modified files in parent repo
git add other-changed-files
Step 4: Commit & Push Parent Repo
git commit -m "chore(submodules): update N submodule pointers
- submodule1: brief description
- submodule2: brief description
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>"
git push
Pre-commit hooks: If markdownlint or other hooks fail, auto-fix and retry.
Step 5: Recursive Init
git submodule update --init --recursive
Verify no errors:
git submodule update --init --recursive 2>&1 | grep -i "fatal\|error"
# Expected: no output
Step 6: Fix Orphaned Entries (if --fix-orphans)
Detect entries in git tree but missing from .gitmodules:
git ls-tree -r HEAD | grep '^160000' | awk '{print $4}' | sort > /tmp/tree.txt
git config --file .gitmodules --get-regexp 'submodule\..*\.path' | awk '{print $2}' | sort > /tmp/mods.txt
comm -23 /tmp/tree.txt /tmp/mods.txt
For each orphaned entry:
- Check if the GitHub repo exists:
gh repo view org/name --json url - If exists:
git submodule add --force <url> <path> - If not:
git rm <path>and commit the removal - Propagate pointer updates through nested chains if needed
Final Verification
git status
# Expected: "nothing to commit, working tree clean" (submodules may show modified content)
Success Output
/git-submodule-commit-all
Step 1: Discovered 6 dirty submodules
+ cloud-backend (new commits)
+ cloud-frontend (new commits)
M coditect-core (modified content)
...
Step 2: Committed & pushed 6 submodules
cloud-backend -> 18160a2 (pushed)
cloud-frontend -> 7b821f8 (pushed)
...
Step 3: Staged pointer updates in parent
Step 4: Committed & pushed parent
b3d5e724 chore(submodules): update 6 submodule pointers
Step 5: Recursive init
68 submodules initialized, 0 errors
COMPLETE: All submodules committed, pushed, and initialized.
Failure Indicators
This command has FAILED if:
- Submodule commit fails (merge conflicts, permission denied)
- Push rejected (force push not allowed, auth failure)
- Parent commit blocked by pre-commit hooks that can't be auto-fixed
- Recursive init produces
fatal:errors - Orphaned entries remain after
--fix-orphans
When NOT to Use
- Single submodule change - use
/git-syncor manual commit instead - Only need init - use
--init-onlyflag or rungit submodule update --init --recursivedirectly - Read-only submodules - pointer updates only, no submodule commits needed
Related
- Skill: submodule-orchestration-patterns
- Command: /git-sync - Sync coditect-core specifically
- Command: /sync - One-command framework sync
- Command: /submodule-status - Health status report
- Agent: submodule-orchestrator - Full lifecycle management
Version: 1.0.0 Created: 2026-02-01 Author: CODITECT Core Team