Non-interactive hunk-by-hunk and line-by-line staging for git
Reason this release was yanked:
Project was rewritten
Project description
git-stage-batch
Hunk-by-hunk and line-by-line staging for git, with both interactive and command-based workflows.
Similar to git add -p but more granular and flexible:
- Interactive mode: Beginner-friendly prompts similar to
git add -p - Command-based mode: Perfect for automation and AI coding assistants
Create atomic, well-structured commits with fine-grained control over what gets staged.
Features
- Interactive mode: Beginner-friendly prompts (like
git add -p) - Command-based mode: Perfect for automation and AI assistants
- Hunk-by-hunk staging: Review and stage individual hunks one at a time
- Line-by-line staging: Stage specific lines within a hunk for maximum granularity
- State persistence: Track processed/skipped hunks across multiple command invocations
- Three operations:
include- stage to indexskip- skip for nowdiscard- remove from working tree
Installation
Recommended (install once, use everywhere):
uv tool install git-stage-batch
Alternative (try without installing):
uvx git-stage-batch start
Quick Start
# Start reviewing hunks
git-stage-batch start
# Include the current hunk (stage it)
git-stage-batch include
# Or use the short alias:
git-stage-batch i
# Or just run with no command (defaults to include when session is active):
git-stage-batch
# Skip it (skip for now)
git-stage-batch skip # or: git-stage-batch s
# Discard it (remove from working tree)
git-stage-batch discard # or: git-stage-batch d
# For fine-grained control, include/skip/discard specific lines
git-stage-batch include-line 1,3,5-7 # or: git-stage-batch il 1,3,5-7
git-stage-batch skip-line 2,4 # or: git-stage-batch sl 2,4
git-stage-batch discard-line 8-10 # or: git-stage-batch dl 8-10
# Check status
git-stage-batch status # or: git-stage-batch st
# Start fresh after committing
git-stage-batch again # or: git-stage-batch a
# Clear all state
git-stage-batch stop
Interactive Mode
For a workflow similar to git add -p, use interactive mode:
git-stage-batch --interactive
Interactive mode presents hunks one at a time with beginner-friendly prompts:
What do you want to do with this hunk?
[i]nclude - Stage this hunk to the index
[s]kip - Skip this hunk for now
[d]iscard - Remove this hunk from working tree (DESTRUCTIVE)
[q]uit - Exit interactive mode
More options: [a]ll, [l]ines, [f]ile, [b]lock, [?]help
Action:
Available Actions
- i / include - Stage this hunk
- s / skip - Skip this hunk for now
- d / discard - Remove from working tree (asks for confirmation)
- q / quit - Exit interactive mode
- a / all - Stage all remaining hunks (asks for confirmation)
- l / lines - Enter line selection sub-menu
- f / file - Stage or skip all hunks in current file
- b / block - Block this file permanently via .gitignore (asks for confirmation)
- ? - Show help
Why Interactive Mode?
- Clear prompts: Explains each option as you go
- Single-letter shortcuts: Fast for power users
- Familiar workflow: Similar to
git add -p
Use interactive mode for manual staging and the command-based workflow for automation or AI assistants.
Commands
Core Operations
start- Find and display the first unprocessed hunk; cache as "current"show(alias:sh) - Reprint the cached "current" hunk (annotated with line IDs)include(alias:i) - Stage the cached hunk (entire hunk) to the index; advanceskip(alias:s) - Mark the cached hunk as skipped; advancediscard(alias:d) - Reverse-apply the cached hunk to the working tree; advancestatus(alias:st) - Show brief state (current hunk summary, remaining line IDs)
Line-Level Operations
include-line IDS(alias:il) - Stage ONLY the listed changed line IDs (+/-) to the indexskip-line IDS(alias:sl) - Mark ONLY the listed changed line IDs as skippeddiscard-line IDS(alias:dl) - Remove ONLY the listed changed line IDs from working tree
File-Level Operations
include-file(alias:if) - Stage the entire file containing the current hunkskip-file(alias:sf) - Skip all hunks in the file containing the current hunkblock-file [PATH](alias:b) - Permanently exclude a file via .gitignoreunblock-file PATH(alias:ub) - Remove a file from permanent exclusion
Session Management
again(alias:a) - Clear state and immediately start a fresh passstop- Clear all state (blocklist and cached hunk)
Special Behavior
- No command - When a session is active, running
git-stage-batchwith no command defaults toinclude
Line ID syntax: Comma-separated list with ranges, e.g. 1,3,5-7
Machine-Readable Output
For scripting and automation, some commands support a --porcelain flag for machine-readable output:
status --porcelain
Outputs JSON with current state:
$ git-stage-batch status --porcelain
{"current_hunk": "file.py :: @@ -10,5 +10,5 @@", "remaining_line_ids": [1, 3, 5], "blocked_hunks": 42, "state_directory": "/path/.git/git-stage-batch"}
Fields:
current_hunk: Summary of current hunk (null if none)remaining_line_ids: Array of unprocessed line IDsblocked_hunks: Count of processed hunksstate_directory: Path to state directory
Example usage:
# Check if a hunk is active
if [ "$(git-stage-batch status --porcelain | jq -r '.current_hunk')" != "null" ]; then
echo "Session active"
fi
# Get remaining line count
git-stage-batch status --porcelain | jq '.remaining_line_ids | length'
show --porcelain
Suppresses output and uses exit codes to indicate hunk presence:
$ git-stage-batch show --porcelain
$ echo $?
0 # Exit 0: hunk exists, Exit 1: no hunk
Example usage:
# Check if hunk exists
if git-stage-batch show --porcelain; then
echo "Current hunk exists"
fi
# Wait for hunk
while ! git-stage-batch show --porcelain; do
sleep 1
done
Configuring Your AI Assistant
This tool is designed for AI coding assistants to create atomic, well-structured commits. Add the following instructions to your project's AI configuration:
For Claude Code
Create or update CLAUDE.md in your repository root:
## Commit Workflow
**Commits** should be atomic and well-structured. Each commit should represent one
logical step in the project's development. The goal is not to preserve the exact
twists and turns of drafting, but to produce a commit history that tells a clear
story of progress.
To aid in this endeavor, use the `git-stage-batch` tool. It provides
functionality similar to `git add -p` in a multi-command flow more suitable for
automation.
### Staging Process
1. Run `git-stage-batch start` to begin the process
2. For each presented patch hunk, run either:
- `git-stage-batch include` (stage this hunk)
- `git-stage-batch skip` (skip this hunk for now)
These commands automatically display the next hunk to evaluate.
3. Repeatedly run these commands until all hunks relevant to the current commit
are processed, then commit the results.
4. Run `git-stage-batch again` to run through all previously skipped
and unprocessed hunks for the next commit.
5. Repeat until all commits are in place.
### Fine-Grained Line Selection
If a hunk is too coarse and contains multiple orthogonal changes, individual lines
may be included or skipped using:
- `git-stage-batch include-line 1,3,5-7` (stage specific lines)
- `git-stage-batch skip-line 2,4` (skip specific lines)
Line IDs are shown in the hunk output as `[#N]` markers.
### Commit Messages
Commit messages should aid **drive-by reviewers with limited context**. Assume
the reader does not know the project well.
Format:
- **First line**: a concise summary with a lowercase prefix (`module:`, `cli:`, etc.)
- **First paragraph**: summarize the code being changed (not the change itself)
- **Second paragraph**: explain the problem with the existing state
- **Third paragraph**: describe how the problem is solved ("This commit addresses
that by...")
Write in the tense that reflects the state **just before** the commit is applied.
For Cursor
Create or update .cursorrules in your repository root with the same instructions as above.
For Other AI Assistants
Most AI coding assistants support project-specific instructions. Add the workflow instructions above to your tool's configuration file. Common locations:
.continuerules(Continue.dev).aider.conf.yml(Aider)- Custom instructions in your IDE settings
Example Workflow
# You have changes in multiple files
$ git status
modified: file1.py
modified: file2.py
# Start staging process
$ git-stage-batch start
file1.py :: @@ -10,5 +10,5 @@
[#1] - old_function()
[#2] + new_function()
context_line()
# Include this change for first commit (using alias)
$ git-stage-batch i
file2.py :: @@ -20,3 +20,4 @@
[#1] + debug_line()
production_code()
# This debug line shouldn't be committed, skip it (using alias)
$ git-stage-batch s
No pending hunks.
# Create first commit
$ git commit -m "refactor: Replace old_function with new_function
The codebase currently uses old_function for processing data.
old_function has a performance bottleneck and doesn't support the new
data format we need.
This commit addresses that by replacing old_function with new_function,
which is 2x faster and handles both old and new data formats."
# Go through skipped hunks for next commit
$ git-stage-batch a
file2.py :: @@ -20,3 +20,4 @@
[#1] + debug_line()
production_code()
# 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
Fast Workflow with Aliases
For even faster operation, use short aliases and the bare command (which defaults to include):
$ git-stage-batch start
[hunk displayed]
$ git-stage-batch # No command = include
[next hunk displayed]
$ git-stage-batch # Include again
[next hunk displayed]
$ git-stage-batch s # Skip this one
[next hunk displayed]
$ git-stage-batch # Include
No pending hunks.
$ git commit -m "..."
$ git-stage-batch a # Again
[first skipped hunk displayed]
How It Works
The tool maintains state in .git/git-stage-batch/:
blocklist- Hashes of hunks you've processed (included, skipped, or discarded)current-hunk.patch- The hunk currently being evaluatedcurrent-lines.json- Structured representation with line IDsprocessed.include/processed.skip- Track line-level decisionssnapshot-base/snapshot-new- File snapshots for accurate reconstruction
State persists across invocations, allowing you to stage changes incrementally.
Development
This project uses uv for dependency management.
# Clone the repository
git clone https://github.com/halfline/git-stage-batch.git
cd git-stage-batch
# Run tests
uv run pytest
# Install from source
uv tool install .
Contributing
See CONTRIBUTING.md for commit message guidelines and development workflow.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file git_stage_batch-0.2.0.tar.gz.
File metadata
- Download URL: git_stage_batch-0.2.0.tar.gz
- Upload date:
- Size: 19.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b18b0140631f28d3cc459a4f82ab319745d544f338a7669436b4314c167efcf
|
|
| MD5 |
d7e388e03f92380697657b64f57cd089
|
|
| BLAKE2b-256 |
1e03590c1e6f6565ca91b0b5cd131eb22b3fd82c13908c7c0a405712ba715131
|
File details
Details for the file git_stage_batch-0.2.0-py3-none-any.whl.
File metadata
- Download URL: git_stage_batch-0.2.0-py3-none-any.whl
- Upload date:
- Size: 24.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.11
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b81a1847eaa01328c00be0229b5eee0c6c271c029756dc95745e0cc1e965ef9
|
|
| MD5 |
12663e1ca500c9f6e529ff81e02347c4
|
|
| BLAKE2b-256 |
66325dcdbd5e22a5fda1c0511b7ae8fa4c063ecc07e6d1e3650ca40b6ad21a4b
|