git-lines
Non-interactive line-level git staging tool for LLMs and automation.
Overview
git-lines enables programmatic, line-level staging of git changes. It fills the gap left by git add -p, which requires interactive input and cannot be used by LLMs or automation tools.
When an LLM or automated system makes changes to code, those changes are often semantically distinct but physically interleaved in the same file. git-lines allows these systems to autonomously organize changes into clean, semantic commits without human intervention.
The Problem
Git's interactive staging (git add -p) operates at the hunk level and requires a human at a terminal. This creates a limitation for LLMs:
- ✅ LLMs can write code
- ✅ LLMs can run
git commit
- ❌ LLMs cannot use
git add -p (interactive/TUI)
Result: LLMs can only stage entire files with git add <file>, losing the ability to create focused, semantic commits when multiple unrelated changes exist in the same file.
The Solution
git-lines provides a non-interactive CLI for line-level staging:
# 1. View changes with line numbers
git-lines diff
# 2. Stage specific lines by number
git-lines stage flake.nix:137,142
git-lines stage config.nix:10..15
git-lines stage zsh.nix:-20,-21
# 3. Commit as usual
git commit -m "Add new dependencies"
This workflow is fully scriptable and requires no human interaction.
Example: Semantic Commits from Mixed Changes
Consider these changes in one file:
$ git-lines diff vscode/default.nix
vscode/default.nix:
+40: # Allow Stylix to override terminal font
+41: "terminal.integrated.fontFamily" = lib.mkDefault "monospace";
+42: "direnv.restart.automatic" = true;
Git sees this as one atomic hunk. But semantically it's two features:
- Lines 40-41: Theme configuration (related to Stylix)
- Line 42: Direnv settings (unrelated)
With git-lines, an LLM can create two focused commits:
# Commit 1: Theme changes
git-lines stage vscode/default.nix:40..41
git commit -m "feat: add Stylix font override for terminal"
# Commit 2: Direnv changes
git-lines stage vscode/default.nix:42
git commit -m "feat: enable automatic direnv restart"
Each commit is self-contained and semantically coherent.
Installation
From crates.io
cargo install git-lines
From source
git clone https://github.com/Omegaice/git-lines
cd git-lines
cargo install --path .
Shell Completions
# Bash
git-lines completions bash > ~/.local/share/bash-completion/completions/git-lines
# Zsh
git-lines completions zsh > ~/.zfunc/_git-lines
# Fish
git-lines completions fish > ~/.config/fish/completions/git-lines.fish
Usage
Basic Workflow
# 1. Make changes to files (manually or via LLM)
# 2. View unstaged changes with line numbers
git-lines diff
# 3. Stage specific lines
git-lines stage file.nix:10,15,20
# 4. Create commit
git commit -m "Your commit message"
Line Reference Syntax
# Single addition (new line 137)
git-lines stage flake.nix:137
# Range of additions (lines 10-15 inclusive)
git-lines stage config.nix:10..15
# Single deletion (old line 20)
git-lines stage zsh.nix:-20
# Range of deletions
git-lines stage file.nix:-10..-15
# Multiple selections (comma-separated)
git-lines stage config.nix:10,15,20
# Mixed operations
git-lines stage gtk.nix:-10,-11,12
# Multiple files in one command
git-lines stage flake.nix:137 gtk.nix:12 zsh.nix:-15
Advanced Examples
Splitting changes within a single hunk:
$ git-lines diff config.nix
config.nix:
+10: feature_a_enabled = true;
+11: feature_a_timeout = 30;
+12: feature_b_enabled = true;
# Stage only feature A
$ git-lines stage config.nix:10,11
$ git commit -m "Enable feature A with 30s timeout"
# Later, stage feature B
$ git-lines stage config.nix:12
$ git commit -m "Enable feature B"
Staging from multiple non-contiguous hunks:
$ git-lines diff flake.nix
flake.nix:
+7: determinate.url = "github:DeterminateSystems/determinate";
+137: debug = true;
+142: ./flake-modules/home-manager.nix
# Stage lines from different hunks that are semantically related
$ git-lines stage flake.nix:7,142
$ git commit -m "Add determinate and home-manager modules"
Selective staging from mixed additions and deletions:
$ git-lines diff gtk.nix
gtk.nix:
-10: gtk.theme.name = "Adwaita";
-11: gtk.iconTheme.name = "Papirus";
+10: # Theme managed by Stylix
+11: gtk.iconTheme.name = "Papirus-Dark";
+12: gtk.cursorTheme.size = 24;
# Stage only the cursor size addition, ignore theme changes
$ git-lines stage gtk.nix:12
$ git commit -m "Set cursor size to 24"
When to Use