--- name: git-split-push description: "Split large git pushes into smaller batches when pushing to Gitea/GitHub/GitLab fails with 'pack exceeds maximum allowed size' error. Detects size errors, groups files by size, commits and pushes in batches. No LFS required." argument-hint: "[git push error] [large files] [split push]" license: MIT metadata: author: claudekit version: "1.0.0" --- # Git Split Push Split large git pushes into smaller batches when the server rejects them due to size limits. ## When to Use - `git push` fails with: **"fatal: the remote end hung up unexpectedly"** - `git push` fails with: **"pack exceeds maximum allowed size"** - `git push` fails with: **"RPC failed; HTTP 413"** - Any push error mentioning size or pack limits ## How It Works 1. **Detects** all untracked/staged/modified files 2. **Calculates** file sizes and groups into batches (default: 20MB each) 3. **Commits** each batch with a descriptive message: `[split-push] Batch N/M` 4. **Pushes** sequentially, small payloads each time 5. **Reports** success/failure for each batch ## Usage ### Quick Start ```bash # Auto-detect and split push python3 ~/.claude/skills/git-split-push/scripts/batch-push.py # Use larger batches (30MB each) python3 ~/.claude/skills/git-split-push/scripts/batch-push.py --max-size 30 # Check size first, don't push python3 ~/.claude/skills/git-split-push/scripts/batch-push.py --check-size # Preview what would happen python3 ~/.claude/skills/git-split-push/scripts/batch-push.py --dry-run ``` ### Command Options | Option | Description | |--------|-------------| | `--max-size N` | Max MB per batch (default: 20) | | `--dry-run` | Preview batches without pushing | | `--check-size` | Show size analysis and exit | | `--untracked-only` | Only push untracked files | | `--verbose` | Show detailed output (default: on) | ## Workflow ### When You Get a Push Error 1. **Don't panic** — the skill will fix it 2. **Run the script** — it handles everything automatically 3. **Check the output** — each batch shows success/fail status 4. **Done** — all files are pushed in smaller chunks ### Example Session ``` $ git push Enumerating objects: done. Counting objects: 100% Delta compression using up to 8 threads. Compressing objects: done. fatal: the remote end hung up unexpectedly pack exceeds maximum allowed size $ python3 ~/.claude/skills/git-split-push/scripts/batch-push.py 🚀 Starting split push (5 batches, max 20 MB each): 📦 Batch 1/5: 18.5 MB (23 files) ✅ Pushed batch 1 📦 Batch 2/5: 19.2 MB (31 files) ✅ Pushed batch 2 📦 Batch 3/5: 20.1 MB (28 files) ✅ Pushed batch 3 📦 Batch 4/5: 17.8 MB (19 files) ✅ Pushed batch 4 📦 Batch 5/5: 15.3 MB (15 files) ✅ Pushed batch 5 ============================================================ Git Split Push — Summary ============================================================ Total files to push: 116 Total size: 91.2 MB Batch size limit: 20 MB Batches created: 5 Batches failed: 0 ✅ All batches pushed successfully! ``` ## Handling Oversized Files If a **single file exceeds the batch limit** (e.g., a 100MB video): ``` ⚠️ Batch 3 SKIPPED (file too large) - video.mp4 (105.3 MB) 💡 To push this file, either: 1. Split the file manually: split --bytes=40M large.zip 2. Remove it from git tracking 3. Use Git LFS (requires server support) ``` **Options for oversized files:** 1. **Split the file** (if it's a zip/ archive): ```bash split --bytes=40M large.zip part- git add part-* git commit -m "Split archive" ``` 2. **Compress first**: ```bash tar -czf archive.tar.gz large-folder/ git add archive.tar.gz ``` 3. **Use Git LFS** (if server supports it): ```bash git lfs install git lfs track "*.mp4" git add .gitattributes video.mp4 ``` 4. **Remove from git** (if not needed): ```bash git rm --cached video.mp4 echo "video.mp4" >> .gitignore ``` ## Technical Details ### Batching Algorithm 1. Sort files by size (largest first) 2. Add files to current batch until reaching max size 3. If single file exceeds max, add it as a single-file batch (will be skipped) 4. Move to next batch when limit reached ### Batch Size Selection | Server Limit | Recommended `--max-size` | Why | |-------------|--------------------------|-----| | 50 MB (Gitea default) | 20 MB | 50% safety margin | | 100 MB (GitHub) | 40 MB | Leave room for git overhead | | 500 MB (GitHub LFS free) | 100 MB | Only if needed | ### Safety Features - **Soft reset** on push failure — doesn't lose work - **Per-batch commits** — can cherry-pick if needed - **Size checking** — prevents pushing obviously oversized files - **Dry run mode** — preview before executing ## Alias (Optional) Add to your `.bashrc` or `.zshrc` for quick access: ```bash alias git-split='python3 ~/.claude/skills/git-split-push/scripts/batch-push.py' ``` Then use: ```bash git-split # Split push all changes git-split --max-size 30 # Use 30MB batches git-split --dry-run # Preview first ``` ## Exit Codes | Code | Meaning | |------|---------| | 0 | Success (all batches pushed or nothing to push) | | 1 | Error (not a git repo, no branch, etc.) | ## Related Skills - `git-cleanup` — Clean up large files from git history - `git-lfs` — Git LFS setup for binary files