giff
Stacked diffs for GitHub. Work on multiple dependent pull requests as a linear stack of branches, with automatic PR management and conflict-aware rebasing.
● main
│
◉ feat/auth-base PR #42 [open] ← you are here
│
◉ feat/auth-tokens PR #43 [open]
│
◉ feat/auth-middleware PR #44 [draft]
Install
From crates.io (requires Rust ≥ 1.75):
The crate is published as giffstack; the binary it ships is giff.
From a local checkout (for hacking on it):
Auth:
Set a GitHub personal access token with repo scope:
# or add it to ~/.config/giff/config.toml (run `giff init` to create the skeleton)
Usage
# Start a stack from main
# Navigate
# Open / update PRs for all frames
# See the stack with live PR status
# See where you are
# Rebase the whole stack onto updated main
# If a conflict occurs, resolve it, then:
# Advanced
Configuration
~/.config/giff/config.toml (created by giff init):
[]
= "ghp_..."
= "https://api.github.com" # override for GitHub Enterprise
[]
= "main" # base branch for new stacks
= true # open PRs as drafts by default
Stack metadata is stored in .git/stacked.toml — inside .git/ so it's never committed.
How it works
Each stack frame is a regular git branch. PRs target the frame below them (not main directly), so reviewers see only the diff for that layer. On giff push, each PR description gets a small JSON block embedded in a fenced code block — this lets the stack be reconstructed from GitHub alone, with no local file required.
Contributing
Pull requests welcome. Please open an issue first for anything beyond small bug fixes.
License
MIT