git-gud (gg)
A stacked-diffs CLI tool for GitHub and GitLab, inspired by Gerrit, Phabricator/Arcanist, and Graphite.
[!CAUTION] This tool has been vibe coded for myself and hasn't been battle tested yet. Do not use! You might bork your git repository!
What are Stacked Diffs?
Stacked diffs allow you to break large changes into small, reviewable commits that build on each other. Each commit becomes its own Pull Request (GitHub) or Merge Request (GitLab), with proper dependency chains. This enables:
- Faster reviews - Small, focused changes are easier to review
- Parallel work - Start the next feature while waiting for review
- Clean history - Each commit is a logical unit of change
Installation
From source
From crates.io
Prerequisites
git-gud automatically detects your remote provider from the URL (github.com or gitlab.com) and uses the appropriate CLI tool.
Self-hosted instances: For GitHub Enterprise or self-hosted GitLab (e.g.,
gitlab.mycompany.com), rungg setupto manually select your provider.
Authenticate with your provider before using git-gud:
# For GitHub
# For GitLab
Quick Start
# Create a new stack
# Make changes and commit (normal git workflow)
&&
&&
&&
# View your stack
# Sync with remote (creates PRs/MRs)
# Navigate within the stack
# After review feedback, modify a commit
# make changes...
# Land approved PRs/MRs
# Clean up merged stacks
Commands
Stack Management
| Command | Description |
|---|---|
gg co <name> |
Create a new stack, switch to existing, or checkout from remote |
gg ls |
List current stack commits with PR/MR status |
gg ls --all |
List all stacks in the repository |
gg ls --remote |
List remote stacks not checked out locally |
gg clean |
Remove merged stacks and their remote branches |
Syncing
| Command | Description |
|---|---|
gg sync |
Push all commits and create/update PRs/MRs |
gg sync --draft |
Create new PRs/MRs as drafts |
gg sync --force |
Force push even if remote diverged |
gg sync --update-descriptions |
Update PR/MR titles and descriptions to match commit messages |
Navigation
| Command | Description |
|---|---|
gg first |
Move to the first commit in the stack |
gg last |
Move to the last commit (stack head) |
gg prev |
Move to the previous commit |
gg next |
Move to the next commit |
gg mv <target> |
Move to a specific commit (by position, GG-ID, or SHA) |
Editing
| Command | Description |
|---|---|
gg sc |
Squash staged changes into current commit |
gg sc --all |
Squash all changes (staged + unstaged) |
gg reorder |
Reorder commits interactively |
gg absorb |
Auto-distribute changes to appropriate commits |
Landing
| Command | Description |
|---|---|
gg land |
Merge the first approved PR/MR (squash by default) |
gg land --all |
Merge all approved PRs/MRs in sequence |
gg land --wait |
Wait for CI to pass and approvals before merging |
gg land --all --wait |
Wait and merge all PRs/MRs in sequence |
gg land --no-squash |
Merge using merge commit instead of squash |
gg land --clean |
Automatically clean up stack after landing all PRs/MRs |
gg land --no-clean |
Disable automatic cleanup (overrides config default) |
gg rebase |
Rebase stack onto updated base branch |
Notes:
- The
--waitflag polls for CI status and approvals with a configurable timeout (default: 30 minutes). Configure withland_wait_timeout_minutesin.git/gg/config.json. - The
--cleanand--no-cleanflags control automatic stack cleanup after landing all PRs/MRs. If neither is specified, the behavior is controlled by theland_auto_cleanconfig option (default:false). Use--cleanto enable cleanup for a single command, or--no-cleanto override atrueconfig default.
Utilities
| Command | Description |
|---|---|
gg setup |
Generate or update .git/gg/config.json interactively |
gg lint |
Run lint commands on each commit |
gg continue |
Continue after resolving conflicts |
gg abort |
Abort current operation |
gg completions <shell> |
Generate shell completions |
Configuration
Configuration is stored in .git/gg/config.json. Run gg setup to generate it interactively:
Configuration Options
All configuration options are in the defaults section:
| Option | Type | Description | Default |
|---|---|---|---|
provider |
string |
Git hosting provider ("github" or "gitlab"). Required for self-hosted instances. |
Auto-detect from URL |
base |
string |
Default base branch for new stacks | Auto-detect (main/master/trunk) |
branch_username |
string |
Username prefix for branch naming | Auto-detect via gh whoami/glab whoami |
lint |
array |
Lint commands to run on each commit with gg lint |
[] |
auto_add_gg_ids |
boolean |
Automatically add GG-IDs to commits without prompting | true |
land_wait_timeout_minutes |
number |
Timeout in minutes for gg land --wait |
30 |
land_auto_clean |
boolean |
Automatically clean up stack after landing all PRs/MRs | false |
Example configuration:
How It Works
Branch Naming
- Stack branch:
<username>/<stack-name>(e.g.,nacho/my-feature) - Per-commit branches:
<username>/<stack-name>--<entry-id>(e.g.,nacho/my-feature--c-abc1234)
GG-ID Trailers
Each commit gets a stable GG-ID trailer that persists across rebases:
Add user authentication
Implement JWT-based auth with refresh tokens.
GG-ID: c-abc1234
This ID is used to track which PR/MR corresponds to which commit, even after reordering or amending.
PR/MR Dependencies
PRs/MRs are created with proper target branches:
- First commit targets the base branch (e.g.,
main) - Subsequent commits target the previous commit's branch
This creates a chain of dependent PRs/MRs that can be reviewed and merged in order.
Example Workflow
# 1. Start a new feature
# 2. Develop incrementally
&&
&&
&&
# 3. Check your stack
)
) ()
) ()
) ()
# 4. Push to remote
)
)
)
# 5. Address review feedback on commit 1
# 6. Re-sync
# 7. Land when approved
# 8. Clean up
)
Working with Remote Stacks
You can continue working on stacks from another machine:
# List stacks that exist on remote but not locally
) )
# Check out a remote stack
# Continue working normally
Shell Completions
Generate completions for your shell, then enable them in your shell config:
# Bash
# Add to ~/.bashrc (if bash-completion isn't already enabled)
# source /usr/share/bash-completion/bash_completion
# or on some distros:
# source /etc/bash_completion
# Zsh
# Add to ~/.zshrc
# fpath=(~/.zfunc $fpath)
# autoload -Uz compinit && compinit
# Fish
Troubleshooting
"gh CLI not installed" / "glab is not installed"
Install the appropriate CLI for your provider:
# GitHub CLI (macOS)
# GitLab CLI (macOS)
# Other platforms
# GitHub: https://cli.github.com/
# GitLab: https://gitlab.com/gitlab-org/cli#installation
"Not authenticated with GitHub/GitLab"
Run the appropriate auth command:
"Not on a stack branch"
You're on a branch that doesn't follow the <user>/<stack> naming convention. Use gg co <name> to create or switch to a stack.
"Merge commits are not supported"
Stacks must have linear history. Rebase your branch to remove merge commits:
Contributing
Contributions are welcome! Please see the design document for architecture details.
License
MIT License - see LICENSE for details.