git-stk 0.4.1

Git-native stacked branch workflow helper
Documentation

git-stk

Git-native stacked branch workflow helper with GitHub and GitLab review integration.


git-stk keeps stacks as ordinary Git branches. Stack parent metadata is stored locally in .git/config as branch.<name>.stkParent, and GitHub PR bases or GitLab MR target branches can be used to reconstruct that metadata.

Status

This project is experimental. The current implementation focuses on local stacked branch workflows plus provider-backed review lookup, sync, submit, and cleanup. It does not replace Git's branch model or attempt automatic conflict resolution.

Install

curl https://larakelley.com/sh/git-stk | bash

Installers are also attached to GitHub Releases, or install from crates.io with cargo install git-stk --locked.

Then install the man page and wire up shell completions (idempotent; prompts before touching your shell rc):

git stk setup

Upgrade an installer-managed copy with:

git stk upgrade

Shell Completions

git stk setup configures these automatically. Completions are dynamic: the shell asks the binary for candidates at completion time, so subcommands, flags, and even branch names complete (git stk up <TAB> offers only the current branch's stack children). The installed binary prints its own registration script, so completions stay in sync across upgrades:

# bash: add to ~/.bashrc
source <(git stk completions bash)

# zsh: write to a directory on your fpath
git stk completions zsh > "${fpath[1]}/_git-stk"

Elvish, fish, and PowerShell are also supported. The bash and zsh output includes a wrapper so git's own completion can complete git stk <TAB> in addition to git-stk <TAB>.

Install For Development

just install
just check
cargo install --path .

After installation, Git can use the binary as a sub-command:

git stk list

Commands

Local stack metadata:

git stk new <branch>
git stk parent [branch]
git stk children [branch]
git stk list [--markdown]
git stk adopt <branch> --parent <parent>
git stk detach [branch]

list prints the stack leaf-first, like a pile sitting on its base, with the trunk labeled:

    feature/b *
  feature/a
main (trunk)

list --markdown prints a shareable summary instead - a status line and the PRs in merge order with links and states, ready to paste into Slack or a tracking issue:

2 PRs, base `main`, 1 open / 1 merged

1. [Bottom change (#9)]https://github.com/owner/repo/pull/9 - merged
2. [Top change (#10)]https://github.com/owner/repo/pull/10 - open

Branches without reviews degrade to plain names, so it works before submitting too.

Navigation and re-stacking:

git stk up [branch]   # towards the top of the stack (children)
git stk down          # towards the trunk (parent)
git stk restack [--update-refs | --no-update-refs] [--push | --no-push]
git stk continue
git stk abort

Provider-backed workflows:

git stk provider
git stk config
git stk status [branch]
git stk review [branch]
git stk sync [branch] [--dry-run]
git stk repair [--dry-run]
git stk submit [branch] [--dry-run] [--push | --no-push]
git stk submit --stack [--dry-run] [--push | --no-push]
git stk cleanup [branch] [--dry-run] [--delete-branch]

submit --push (or git config stk.pushOnSubmit true) pushes the submitted branches with -u --force-with-lease before creating or updating reviews, so new branches exist remotely and rebased ones are updated safely.

submit --stack also maintains a stack overview at the end of every PR/MR description: the full stack as linked bullets (leaf-first, with a pointer on the PR being viewed) sitting on the trunk, plus a footer crediting the tool. The section lives between HTML comment markers and self-repairs on the next submit if the markup is hand-edited away.

Upgrading:

git stk upgrade              # upgrade to the latest release
git stk upgrade --force      # reinstall the latest release even if up to date
git stk upgrade --head [-y]  # build and install the latest unreleased commit

upgrade uses the install receipt written by the shell installer; copies installed with cargo install should upgrade through cargo instead. --head requires a Rust tool-chain, prompts before installing a pre-release build, and git stk upgrade --force returns you to the latest release afterwards.

Configuration

All settings live under [stk] in git config, so the tool's footprint stays separated from git's own. Everything is optional; defaults shown below:

[stk]
    ; Review provider: github or gitlab. Default: auto-detect from the remote URL.
    provider = github
    ; Remote used for provider detection and pushes. Default: origin.
    remote = origin
    ; Pass --update-refs to git rebase during restack. Default: false.
    updateRefs = true
    ; Force-push (with lease) every rebased branch after restack. Default: false.
    pushOnRestack = true
    ; Push branches (-u --force-with-lease) before submitting reviews. Default: false.
    pushOnSubmit = true

The tool also manages per-branch metadata: branch.<name>.stkParent (the stack parent) and branch.<name>.stkBase (the recorded fork point). These are written by new, adopt, sync, restack, and cleanup; you normally never touch them by hand.

Branches are the real state; the metadata is just annotation. If it is ever lost or stale, git stk repair rebuilds it from review bases (when gh/glab is available) and branch ancestry, and verifies recorded fork points. Anything it cannot resolve safely is reported for a manual git stk adopt.

Inspect everything stk reads or wrote with:

git stk config

Providers

Provider detection uses stk.provider first, then stk.remote, then origin. GitHub support shells out to gh. GitLab support shells out to glab. Authenticate those CLIs before using provider commands.

Re-stacking

restack follows the stk.updateRefs config (default false). Use --update-refs or --no-update-refs to override that for one run. If a rebase conflicts, git-stk records state in .git/stack-state; resolve conflicts and run git stk continue, or run git stk abort.

git-stk records each branch's fork point in .gitconfig as branch.<name>.stkBase and rebases with --onto, so only a branch's own commits are replayed. This makes restacking safe after a parent is squash-merged, rebase-merged, or amended. A missing or stale fork point falls back to a plain rebase.

After a restack, every rebased branch's remote counterpart is stale. Pass --push (or set git config stk.pushOnRestack true) to force-push (with lease) all rebased branches automatically, including after a conflicted restack finishes via git stk continue. Without it, restack prints the exact push command instead. --no-push overrides the config for one run; stk.remote picks the remote (default origin).

Generated Assets

Shell completions and a man page can be generated with:

just generate-assets

Generated files are written under target/generated.

Project Tasks

just build
just test
just lint
just check

License

Copyright (c) 2026 Lara Kelley. MIT License. See LICENSE.