This file provides guidance to WARP (warp.dev) when working with code in this repository.
zsh-grob (Git Rebase Onto Branch) is an interactive wrapper around git rebase --onto. It uses fzf to create a step-by-step workflow for moving commit ranges between branches, with the killer use case being management of stacked pull requests.
The project provides two distribution methods:
- git-grob: Standalone executable invoked as
git grob(installable via Homebrew or manual install) - zsh-grob.plugin.zsh: Oh-My-Zsh plugin invoked as
grob
- git-grob: Standalone executable with shebang (
#!/usr/bin/env zsh). Usesexitinstead ofreturnfor error handling. - zsh-grob.plugin.zsh: Oh-My-Zsh plugin that defines a
grob()function. Usesreturnfor flow control.
Both files contain identical logic with minor differences in exit/return handling.
Interactive Flow: The function implements a three-step wizard:
- Branch selection (target destination)
- Commit selection (oldest commit to move, inclusive)
- Preview and confirmation
Preview System: Uses fzf's --preview flag with inline shell commands to show:
- Branch history during branch selection
- Rich commit details (author, date, stats, full diff) during commit selection
- Constructs complex preview commands using heredoc-style string interpolation
Commit Range Calculation: Instead of requiring users to understand HEAD~N syntax, the plugin:
- Uses
git log --oneline | grep -nFto find the line number of the selected commit - Converts that to
HEAD~Nformat for the rebase command - Builds
git rebase --onto <target> HEAD~N <flags...>
Cross-Platform Compatibility: The preview command in lines 44-57 carefully handles:
sedescape sequences that work on both BSD (macOS) and GNU (Linux)awkstring escaping for Zsh context (note the\"patterns)tputfor ANSI colors instead of hardcoded escape codes
# Test the git-grob executable directly
./git-grob
# Test with flags
./git-grob -i
./git-grob --autosquash
# Test as git subcommand (requires git-grob to be in PATH)
export PATH="$PWD:$PATH"
git grob# After making changes, reload the function
source zsh-grob.plugin.zsh
# Test in a git repository with branches
grob
# Test with flags
grob -i
grob --autosquashTo test stacked PR scenarios (the primary use case):
# Create test branches
git checkout -b branch_A main
# Make commits...
git checkout -b branch_B branch_A
# Make more commits...
# Simulate A being updated
git checkout branch_A
git commit --amend # or add more commits
git checkout branch_B
# Now test: grob should help rebase B onto new AHomebrew (local testing):
# Test the formula locally before publishing
brew install --build-from-source ./git-grob.rb
git grob # Test it works
brew uninstall git-grob # Clean upManual installation:
# Install to local bin
cp git-grob /usr/local/bin/
chmod +x /usr/local/bin/git-grob
git grob # Test it worksOh-My-Zsh plugin:
# Copy to custom plugins directory
cp zsh-grob.plugin.zsh ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/grob/grob.plugin.zsh
source ~/.zshrc
grob # Test it worksZsh Idioms: This plugin uses Zsh-specific features:
read -k 1for single-character input- Array syntax:
${#extra_flags[@]}and"${extra_flags[@]}" - Conditional regex matching:
[[ "$confirm" =~ ^[Yy]$ ]]
Terminal Formatting: Uses tput consistently for all terminal control (bold, colors, reset). When editing, maintain this pattern rather than using raw ANSI codes.
Preview Command Construction: Lines 44-57 contain a complex multi-line string for fzf --preview. When editing:
- Inner quotes must be escaped for Zsh (
\") - The
sedcommand uses\$dto delete the last line (works on both BSD/GNU) - Color codes use
tputwrapped in command substitution within the string
- Zsh: Required (this is a Zsh plugin)
- fzf: Required for interactive selection (checked at runtime)
- Git: Required (assumed to be present)
Adjusting Preview Window Size: Modify --preview-window flags:
- Branch preview (line 34):
--preview-window=up:40% - Commit preview (line 63):
--preview-window=up:6:wrap
Changing Preview Content: Edit the preview_cmd variable (lines 44-57). Remember to test on both macOS and Linux if changing sed or awk usage.
Adding Git Flags: The extra_flags array is passed through to the final rebase command. All unknown arguments to grob are treated as flags for git rebase.
Commented Code: Lines 100-194 contain a commented-out previous version. This appears to be kept for reference (possibly showing the evolution of the sed/awk escaping fixes mentioned in line 43).
Dirty Worktree Check: Lines 25-28 prevent rebasing with uncommitted changes. This is a safety feature and should be preserved.
Base Reference Calculation: Line 71 (base_ref="HEAD~$commit_index") is the critical calculation that translates the user's selection into the correct rebase syntax. The index is 1-based (from grep -n), which correctly maps to HEAD~N.
- Tag a new version:
git tag v1.0.0 && git push origin v1.0.0 - Generate SHA256 of release tarball:
curl -sL https://github.com/sspathak/zsh-grob/archive/refs/tags/v1.0.0.tar.gz | shasum -a 256 - Update
git-grob.rbwith the correct version and SHA256 - Create a tap repository at
github.com/sspathak/homebrew-tap - Copy
git-grob.rbto the tap repository
zsh-grob/
├── git-grob # Standalone executable (can be invoked as 'git grob')
├── zsh-grob.plugin.zsh # Oh-My-Zsh plugin (defines grob() function)
├── git-grob.rb # Homebrew formula
├── README.md # User documentation
├── WARP.md # AI agent guidance
├── LICENSE # MIT License
└── file.txt # Test file (not part of distribution)