Git commands for yak-shaving and stacking PRs.
git yak <name> pause to do something small without leaving your branch
git yak --branch <name> insert a branch beneath your current work
git stack <name> stack a new branch on top of the current one
git stack-pr <title> push and create a PR for the bottom branch
git sync rebase the stack, cleaning up merged branches
git stack-tree print the branch stack
./install.sh # symlinks into ~/.local/bin (default)
./install.sh --copy # copies instead of symlinking
./install.sh --uninstallYou're mid-flow on feature and notice a typo. You don't want to start
a new branch for a one-line fix.
git yak typo-fix
# fix the typo, commit it
git yak --donegit yak <name> stashes your in-progress work and leaves you on the
current branch. You make the fix and commit it directly. git yak --done
pops the stash back. Yak commits land on the current branch and ship with it.
Nest as deep as you want — each --done unwinds one level. Use
git yak --abort instead to throw the yak away (commits discarded,
stash dropped).
If the yak grows beyond a quick fix and you want it reviewed and merged on its own:
Before:
main
└─ feature ← you are here, mid-work
git yak --branch refactorAfter:
main
└─ refactor ← you are here, do the refactor
└─ feature ← moved on top, waiting
The script stashes uncommitted changes, creates refactor directly
beneath feature, rebases feature onto it, and drops you on
refactor. When done:
git yak --donemain
└─ refactor ← ready for review
└─ feature ← you are back here, stash restored
You finished part-1 and want to keep building on top.
Before:
main
└─ part-1 ← you are here, done but not merged
Motivation: part-1 is in review. You don't want to wait — you want to
start part-2 on top, so it's ready the moment part-1 lands.
git stack part-2After:
main
└─ part-1
└─ part-2 ← you are here
You're ready to send the bottom branch for review.
Before:
main
└─ part-1
└─ part-2 ← you are here
Motivation: only the bottom branch can be merged next. stack-pr finds
it and opens the PR against main — no checkout needed.
git stack-pr "Add feature part 1"After: part-1 is pushed and a PR is open against main. You stay on
part-2 and keep working.
PR #1 (part-1) gets merged.
Before:
main
└─ part-1 ← merged
└─ part-2 ← you are here
Motivation: main moved forward. The stack needs to be rebased onto the new main, and the merged branch cleaned up.
git syncAfter:
main ← includes part-1
└─ part-2 ← rebased onto new main (you are here)
git sync detects that part-1 was merged, deletes it, and rebases
everything above onto the new main. Works with squash merges,
rebase-and-merge, and regular merge commits.
Branch relationships are stored in git config as branch.<name>.stack-parent.
git stack-tree prints the current stack:
$ git stack-tree
main
└─ refactor [2]
└─ feature [3] ←The [N] is the commit count. The ← marks the current branch.
All commands print the tree after completing, so you always know where
you are.
./test.shgit stack-prrequires the GitHub CLI (gh).- The scripts assume your remote is named
origin. - If
init.defaultBranchis not set, the scripts default tomain:git config init.defaultBranch develop # if your trunk is different - If you rename or delete branches outside these commands, the
stack-parentconfig can go stale. Clean it up withgit config --remove-section branch.<name>.