npx claudepluginhub mrmans0n/git-gud --plugin git-gudThis skill uses the workspace's default tool permissions.
Use this skill to operate **git-gud (`gg`) as a CLI tool** for day-to-day stacked-diff workflows across GitHub and GitLab.
Manages stacked branches and pull requests using gh-stack GitHub CLI extension for creating, pushing, rebasing, syncing, navigating, and viewing dependent PR stacks in incremental code review workflows.
Use Mergify stacks for git push, commit, branch, and PR creation. ALWAYS use this skill when pushing code, creating commits, creating branches, or creating PRs. Triggers on push, commit, branch, PR, pull request, stack, stacked, git, rebase, checkout, reorder, move, sync, amend, note, revision history.
Provides Git workflow guidance on branching strategies (GitHub Flow, Trunk-Based, GitFlow), conventional commits, merge vs rebase, conflict resolution, and team best practices. Activate for project setup, PRs, releases, onboarding.
Share bugs, ideas, or general feedback.
Use this skill to operate git-gud (gg) as a CLI tool for day-to-day stacked-diff workflows across GitHub and GitLab.
--json)gg installedgh auth statusglab auth statusgg initialized (gg setup)Note: Network errors during auth check are non-fatal — gg prints a warning and continues. The operation may fail later if authentication is actually required.
gg setup # Quick mode: essential settings (provider, base, username)
gg setup --all # Full mode: all settings organized by category
Quick mode prompts for: provider, base branch, username.
Full mode organizes all settings into groups: General, Sync, Land, Lint, Worktrees, and GitLab (if applicable). Includes sync_draft, sync_update_descriptions, and sync_update_title options.
Store shared defaults in ~/.config/gg/config.json that apply to all repos. Local config (gg setup) takes precedence.
.git/gg/config.json){
"defaults": {
"provider": "github",
"base": "main",
"branch_username": "your-github-user",
"lint": ["cargo fmt --all --check", "cargo clippy -- -D warnings"],
"auto_add_gg_ids": true,
"sync_auto_rebase": false,
"sync_behind_threshold": 1,
"sync_auto_lint": false,
"sync_draft": false,
"sync_update_descriptions": true,
"sync_update_title": false,
"land_auto_clean": false,
"land_wait_timeout_minutes": 30,
"unstaged_action": "ask"
}
}
{
"defaults": {
"provider": "gitlab",
"base": "main",
"branch_username": "your-gitlab-user",
"lint": ["cargo fmt --all --check", "cargo clippy -- -D warnings"],
"gitlab": {
"auto_merge_on_land": false
}
}
}
auto_add_gg_ids is deprecated and kept only for compatibility with existing configs; runtime behavior always treats it as enabled.
gg co -w feature-auth
When splitting an existing stack into lower and upper stacks, prefer a managed worktree for the new upper stack:
gg unstack --target 3 --name feature-auth-followup --wt
git add <files>
git commit -m "feat: add input validation"
gg ls --json # single-stack details + summary metrics
gg log --json # smartlog-style view of the current stack
gg inbox --json # cross-stack triage buckets for action needed
gg sync --json
If a mapped PR/MR still points at an old source branch after a stack split,
gg sync recreates that PR/MR with the current entry branch, remaps config to
the new number, comments on the old one, and closes it. JSON action is
"recreated".
If gg sync --json returns a warning that the stack branch does not use the
configured prefix, surface it to the user. The command may continue, but stack
discovery/listing and saved PR/MR mappings can be inaccurate until the branch is
renamed to match defaults.branch_username.
gg land -a -c --json
gg land without explicit user confirmation.--json for gg ls, gg sync, gg land, gg clean -a, and gg lint.gg co -w <stack>).approved: true and ci_status success before landing. If the user requests --admin, skip the approval check (GitHub only — GitLab ignores the flag).gg rebase first.gg absorb -s for multi-commit edits.git add -A blindly. Review git status first and only stage intended files. Use git add <specific-files> to avoid leaking secrets, env files, or unrelated changes.gg sc, gg absorb, gg reorder/gg arrange, gg split, gg unstack, gg drop, gg rebase, gg restack) refuse to rewrite merged PRs/MRs or commits already on the base branch, except that gg rebase silently skips base-ancestor commits that naturally drop out when rebasing onto the refreshed base. If a command exits with ImmutableTargets, surface the listed commits and reasons to the user and get explicit confirmation before retrying with -f / --force (alias --ignore-immutable).gg mv, gg first, gg last, gg prev, gg nextgg sc / gg sc -agg absorb -sgg split — opens a two-panel TUI for hunk selection (files on the left, colored diff on the right), followed by inline commit message inputs for both the new and remainder commits. Use --no-tui to fall back to sequential git add -p style prompts. The -m flag bypasses the TUI message input for the new commit. The --no-edit flag skips the remainder message input. Pass FILES... to auto-select all hunks from those files (e.g., gg split -c 3 file1.rs file2.rs).gg unstack — opens a picker by default. The selected entry and descendants become a new independent stack; lower entries remain in the original stack. Use --target <position|gg-id|sha> --no-tui for scripts, and --name <stack> to choose the new stack name.gg drop <position|sha|gg-id>... -y (alias: gg abandon). Use -y / --yes to skip confirmation; add -f / --force only to bypass the immutability guard for merged/base-ancestor commits.gg reorder (or gg arrange) — opens interactive TUI for visual reordering and dropping commits. Press d to mark a commit for dropping. Use --no-tui to fall back to text editor (delete lines to drop).gg reorder -o "3,1,2"gg sync -u <position|gg-id|sha> --jsongg lint --jsongg run -- <cmd...> (see below)gg inbox --jsongg restack / gg restack --dry-run --json (see below)gg clean -a --jsongg undo (see below)gg undo)gg undo reverses the ref/HEAD effects of the most recent mutating
gg command by replaying a snapshot from the per-repo operation log at
<commondir>/gg/operations/*.json. It never touches the working tree,
index, or untracked files — only refs move.
gg undo # reverse the most recent local operation
gg undo --list # see recent operations (newest-first)
gg undo <op_id> # target a specific record from --list
gg undo; gg undo # redo: a second undo reverses the first
gg undo --json # machine-readable output
Every mutating command (sc, drop, split, unstack, rebase, reorder,
absorb, reconcile, restack, checkout, nav, clean, sync, land,
and run --amend) snapshots the refs it will touch before mutating and
records the operation on success. The log keeps the last 100 records;
interrupted/pending records are never pruned.
Refusal modes (exit 1, no refs touched, JSON includes refusal.reason):
remote — target operation pushed/merged/closed/created a PR/MR.
gg prints a provider-specific revert hint (gh pr close <n>,
glab mr close <n>, git push --delete …). Agents must surface the
hint to the user rather than attempt silent remote rollback.interrupted — operation crashed or was Ctrl-C'd mid-flight.stale — refs moved since the target operation finalised. The error
names the ref, expected OID, and actual OID.unsupported_schema — record was written by a newer gg binary.gg undo does not restore working-tree content (use git reflog or
git stash), does not touch remotes, and does not support an
--all / --range mode.
gg restack)gg restack detects and repairs ancestry drift — when a commit's GG-Parent
trailer no longer matches its expected parent in the stack order. This happens
after manual git rebase, git commit --amend, cherry-picks, or upstream
rebases that rewrite commit SHAs without updating GG metadata.
gg restack --dry-run # show plan without changes
gg restack --dry-run --json # machine-readable plan
gg restack # execute full ancestry repair
gg restack --from 3 # repair only from position 3 upward
gg restack --json # execute with JSON output
Each step in the plan is one of:
--from threshold, not checkedAfter a successful restack, run gg sync to push the repaired commits.
gg run)gg run walks every commit in the current stack (oldest → newest) and
executes a command at each one. Use it for things that don't fit the
lint config — ad-hoc verifications, formatters, single-shot scripts,
etc.
gg run -- cargo test -p mycrate
Each commit is checked out, the command runs, and the tree must stay
clean. Any modification fails that commit (same contract as gg lint
without --amend).gg run --amend -- cargo fmt
Changes the command makes are folded into each commit via
git commit --amend, then the rest of the stack is rebased on top.
This is the same engine gg lint uses.gg run --discard -- ./mutating-check.sh
Runs the command and throws away any changes (working tree + index +
untracked). Useful when you only care about the exit code of a
command that happens to mutate state.--keep-going / -k to continue through failing commits instead
of aborting at the first one.--until <position|gg-id|sha> stops after
the named commit. Everything above it is left untouched.-j N / --jobs N spawns isolated
worktrees per commit. Valid only with the default (read-only) mode.
The dirty-tree check in each worker matches the sequential path
(untracked files are ignored, tracked modifications fail).gg run --json -- <cmd...> emits a single
RunResponse document on stdout (see reference.md). Failures set
run.all_passed = false; the process still exits non-zero, but only
the run payload is printed — no trailing {"error":...} object.Argument boundaries are preserved: gg run -- git commit -m "multi word"
passes exactly those argv elements to git without shell splitting, so
quoted args with spaces, globs, or shell metacharacters go through
intact. Use -- before the command (as shown) so clap treats
subsequent tokens as the command, not as gg run flags.
For repeatable linter runs with commands configured in .git/gg/config.json,
prefer gg lint — it's gg run --amend with the command list coming from
config.
gg refuses by default to rewrite commits that look "already published":
origin/<base> (or the local base, as
a fallback).The guard protects gg sc, gg absorb, gg reorder / gg arrange,
gg split, gg unstack, gg drop, gg rebase, and gg restack. gg rebase is a special case: merged commits (both base-ancestor commits and squash-merged PRs) are silently skipped because git rebase would drop them naturally via patch-id matching instead of rewriting them. For the remaining commands the command exits with an ImmutableTargets error listing every affected position, short SHA, title, and reason (e.g. merged as !123, already in origin/main).
To bypass it intentionally, pass -f / --force (long alias
--ignore-immutable). Always surface the listed commits and reasons to the
user first; the override still emits a warning and proceeds.
gg land's post-merge cleanup bypasses the guard by design, and
gg absorb --dry-run skips it (no rewrite happens). See
reference.md → "Immutable commits" for details.
gg sync uses managed markers to separate generated content from user edits:
(user content — preserved across syncs)
<!-- gg:managed:start -->
(generated by gg — regenerated on every sync)
<!-- gg:managed:end -->
(user content — preserved across syncs)
If the repo's .git/gg/config.json has defaults.stack_nav_comments: true,
gg sync posts and maintains a managed comment on each open PR/MR in the
stack. The comment lists every entry (#N on GitHub, !N on GitLab) with a
👉 marker on the current one. The comment is identified by a hidden
<!-- gg:stack-nav --> marker and managed entirely by git-gud — don't edit
these comments manually, and don't be surprised when gg sync adds, updates,
or removes them automatically.
Disable the feature by setting defaults.stack_nav_comments: false (the
default). The next gg sync then cleans up any existing managed comments.
Reconcile is skipped under --until to avoid partial-stack inconsistencies.
gg land --auto-merge is GitLab-only and requests queueing/auto-merge.gg ls --json with:
in_merge_trainmerge_train_positionqueued / already_queued (in addition to merged).--wait detects CI failure, the error message includes the names and stages of failed pipeline jobs (fetched from the MR's head pipeline).gg sync also handles this if an MR was merged directly in the UI.glab for auxiliary GitLab checks/actions.pr_* naming, even for GitLab MRs (pr_number, pr_state).pr_state values: open, merged, closed, draft (same for both GitHub and GitLab).pr_url format varies by provider (/pull/N for GitHub, /-/merge_requests/N for GitLab).reference.mdexamples/basic-flow.mdexamples/multi-commit.mdexamples/merge-train.mdreference.md → MCP Server sectionThe gg-mcp binary exposes git-gud as an MCP server (stdio transport). Set GG_REPO_PATH to the target repo.
stack_list / stack_log / stack_list_all / stack_status — inspect stacks (stack_log gives a smartlog-style view of the current stack; stack_list_all is cross-stack)pr_info — check PR state, CI, approvalconfig_show — read repo configurationstack_undo_list — list recent operations from the per-repo operation logstack_checkout — create or switch stacksstack_sync — push and create/update PRs (use draft: true for safety)stack_land — merge approved PRs (always confirm with user first)stack_clean — remove merged stacksstack_rebase — rebase onto latest basestack_squash / stack_absorb — amend commitsstack_reconcile — fix out-of-sync remote branchesstack_drop — remove commits from the stack (always passes --yes; set force: true only to bypass the immutability guard for merged/base commits; agent confirms with user before any drop)stack_split — split a commit using interactive hunk selection (TUI opens by default; pass FILES... to auto-select all hunks for those files)stack_reorder — reorder commits with explicit order string (no TUI)stack_restack — repair stack ancestry drift (dry_run, from params)stack_undo — reverse the ref/HEAD effects of the most recent mutating gg command (refuses on remote-touching ops, returns provider-specific revert hints; agents must surface those hints rather than attempt silent remote rollback)stack_move — jump to a commit by position, GG-ID, or SHAstack_navigate — move first/last/prev/next in the stackstack_sync with draft: true for new PRs unless the user asks for non-draft. Note: draft: true only affects newly created PRs, not existing ones.stack_land without explicit user approval.stack_sync, stack_land, stack_clean, and stack_lint.stack_status shows behind_base > 0, run stack_rebase before syncing.stack_squash, stack_absorb, stack_reorder, stack_split, stack_drop, stack_rebase, plus CLI gg unstack) will fail with ImmutableTargets when a target commit is merged or already on the base branch. Each tool accepts a force: bool parameter that maps to --force / --ignore-immutable. Only set force: true after surfacing the affected commits to the user and getting explicit approval. stack_drop always passes --yes (MCP is non-interactive), but its force: bool param is separate from the confirmation-skip — leave it false unless the user has approved rewriting merged/base commits.