Home
┌─────────────────┐
│ git-stage-batch │
└─────────────────┘
o───o
/
o───o───o
stage patches in batches
Git history doesn't have to be.
🎧 git-stage-batch featured on the Deep Dive podcast!
-
Command-Based Workflow
Perfect for automation and AI coding assistants. Chain commands together for precise control.
-
Line-Level Control
Stage specific lines within a hunk for maximum granularity. Perfect for separating mixed changes.
-
Machine-Readable Output
--porcelainflag for scripting. Integrate into your tools and workflows. -
Interactive Mode
Menu-driven hunk-by-hunk workflow inspired by git add -p. Review and stage changes in a continuous session.
-
Named Batches
Defer and label changes for later processing. Advanced patch-series organization for complex workflows.
See it in Action¶

Creating atomic commits: bug fix, validation feature, and build artifact exclusion
Why git-stage-batch?¶
Similar to git add -p but more granular and flexible:
- ✅ Interactive mode - Continuous hunk-by-hunk workflow with menus
- ✅ Command-based mode - Perfect for automation and AI assistants
- ✅ Line-by-line staging - Stage specific lines within a hunk
- ✅ State persistence - Resume staging across multiple invocations
- ✅ Colored output - Clear visual distinction in your terminal
- ✅ File operations - Stage/skip entire files at once
- ✅ No dependencies - Pure Python standard library
Quick Start¶
Installation¶
Basic Usage¶
# Start reviewing hunks
❯ git-stage-batch start
# Include the selected hunk (stage it)
❯ git-stage-batch include
# Or use the short alias:
❯ git-stage-batch i
# Skip it for now
❯ git-stage-batch skip # or: s
# Discard it (remove from working tree)
❯ git-stage-batch discard # or: d
# For fine-grained control, stage specific lines
❯ git-stage-batch include --line 1,3,5-7 # or: il 1,3,5-7
❯ git-stage-batch skip --line 2,4 # or: sl 2,4
# Replacement text must use one contiguous displayed line-ID span
❯ git-stage-batch include --line 1-2 --as 'replacement'
# Exact unchanged edge-overlap lines are stripped by default for line-scoped --as
❯ git-stage-batch include --line 1-2 --as 'keep1\nreplacement\nkeep4'
# Keep those edge-overlap lines literally with --no-edge-overlap
❯ git-stage-batch include --line 1-2 --as 'keep1\nreplacement\nkeep4' --no-edge-overlap
# Or stage full replacement text for one file-scoped path
❯ git-stage-batch include --file path.txt --as 'full staged file text'
# Or replace one file-scoped working-tree path without staging it
❯ git-stage-batch discard --file path.txt --as 'full working tree text'
# Or preserve exact stdin text, including trailing newlines
❯ git-stage-batch include --file path.txt --as-stdin < replacement.txt
❯ git-stage-batch discard --file path.txt --as-stdin < replacement.txt
# Check status
❯ git-stage-batch status # or: st
# Start fresh after committing
❯ git-stage-batch again # or: a
# Stop after one action instead of selecting the next hunk
❯ git-stage-batch include --no-auto-advance
❯ git-stage-batch show
# For advanced workflows, defer changes to named batches
❯ git-stage-batch include --to feature-work # Save to batch for later
See batch operations for advanced patch-series organization.
See commands reference for the --as contiguous-range rules.
Example Workflow¶
# You have changes in multiple files
❯ git status
modified: auth.py
modified: config.py
# Start staging process
❯ git-stage-batch start
auth.py :: @@ -10,5 +10,5 @@
[#1] - old_hash_function()
[#2] + new_hash_function()
validate_user()
# Include this for first commit
❯ git-stage-batch i
config.py :: @@ -20,3 +20,4 @@
[#1] + DEBUG = True
TIMEOUT = 30
# This debug flag shouldn't be committed, skip it
❯ git-stage-batch s
No pending hunks.
# Create first commit
❯ git commit -m "auth: Upgrade to new hash function"
# Go through skipped hunks for next commit
❯ git-stage-batch a
config.py :: @@ -20,3 +20,4 @@
[#1] + DEBUG = True
TIMEOUT = 30
# Discard this debug line instead
❯ git-stage-batch d
No pending hunks.
# Working tree is now clean
❯ git status
nothing to commit, working tree clean
Important: Commit Early, Commit Often¶
git-stage-batch is designed for an incremental workflow:
- Stage hunks that belong in the selected logical commit (
include) - Create that commit (
git commit) - Continue with remaining hunks (
again) - Repeat
The again command shows you only the hunks you skipped - it doesn't re-show hunks you already included and committed.
Features¶
Hunk-by-Hunk Staging¶
Review and stage individual hunks one at a time. Each hunk shows changed lines with IDs for easy reference.
Line-by-Line Staging¶
Stage specific lines within a hunk:
Perfect for separating orthogonal changes that ended up in the same hunk.
Colored Output¶
Automatic color support with TTY detection:
- 🟢 Green for additions
- 🔴 Red for deletions
- 🔵 Cyan for headers
- ⚫ Gray line numbers for easy scanning
State Persistence¶
Track processed/skipped hunks across multiple command invocations. Resume where you left off.
Stale State Detection¶
Automatically detects and clears cached state when files are committed or modified externally. No more misleading status!
FAQ¶
Is this rewriting Git history?¶
No.
git-stage-batch is intended for organizing draft patch sets before they are committed or shared. It helps you turn a messy working tree into a clean sequence of logical commits.
It does not rewrite existing commits, and it is not meant to modify the history of shared or protected branches.
Think of it as helping you prepare commits before they become part of history, not changing history afterward.
When should I use this?¶
Use it while preparing commits for a branch you are working on locally.
A typical workflow looks like:
Then run:
to turn those edits into a clean set of commits.
Once the commits are ready, you can push or open a pull request as usual.
Why not just use git add -p?¶
git add -p is great for staging individual changes, but it is designed for single-pass staging.
git-stage-batch is designed for multi-pass commit curation:
This makes it easier to organize a large working tree into a series of clean commits.
Is this safe for protected branches?¶
Yes — because you should not use it there.
This tool is meant for local development branches before merging.
Once commits are pushed or merged into protected branches, standard Git practices apply and history should normally remain stable.
Is this similar to git rebase -i?¶
It solves a related problem but at a different stage.
git rebase -ireorganizes existing commitsgit-stage-batchhelps you create better commits in the first place
Many developers will still use rebase -i occasionally, but with curated commits it becomes much less necessary.
Why curate Git history at all?¶
Because Git history is read by people.
A raw commit log is a transcript of development: experiments, mistakes, and partial fixes.
A curated history is documentation of how the system evolved. It is far easier for contributors, reviewers, and your future self to understand.
When should I use batches?¶
Most workflows don't need batches. The core commands (include, skip, discard) handle typical staging scenarios.
Use batches when you need to: - Defer specific changes for a separate commit while continuing to process other hunks - Group related changes across multiple files for thematic organization - Temporarily set aside changes you're uncertain about
See the batch operations guide for detailed workflows and examples.
Next Steps¶
-
Get Started
Install and run your first staging session in minutes.
-
Learn the Commands
Complete reference of all commands and options.
-
See Examples
Common workflows and use cases.
-
Configure AI Assistants
Set up Claude, Cursor, or other AI coding assistants.