npx claudepluginhub jacobpevans/claude-code-plugins --plugin git-workflowsThis skill uses the workspace's default tool permissions.
Merge a PR using local `git rebase` + signed commits + `git push origin main`.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Merge a PR using local git rebase + signed commits + git push origin main.
gh pr merge --rebase cannot sign commits. Local rebase with commit.gpgsign=true
signs every rebased commit. Pushing main directly auto-closes the PR.
MANDATORY FIRST STEP: Spawn a Haiku subagent using the Agent tool with
mode: "bypassPermissions". Pass all content starting from Prerequisite: Validate Rulesets
through end-of-document as the agent prompt; include the current branch name and PR number.
Do not execute any steps yourself — the subagent runs the complete workflow autonomously with
all permissions auto-accepted.
If the Haiku subagent cannot be spawned, becomes unavailable, or encounters an unrecoverable error while running this workflow, clearly report the failure to the user and ask whether to (a) retry spawning the subagent or (b) proceed manually by following the remaining steps of this document together step-by-step.
Before anything else, check the all-branches ruleset:
gh api repos/{owner}/{repo}/rulesets \
--jq '.[] | select(.conditions.ref_name.include[] == "~ALL") | .rules[].type'
If any of these appear → ABORT with the message shown:
| Rule type | Message |
|---|---|
non_fast_forward | "Remove from all-branches ruleset. Feature branches need force-push after rebase. Keep on main-only." |
required_linear_history | "Remove from all-branches ruleset. Keep on main-only." |
pull_request | "Remove from all-branches ruleset. Keep on main-only." |
required_status_checks | "Remove from all-branches ruleset. Keep on main-only." |
code_scanning | "Remove from all-branches ruleset. Keep on main-only." |
Only required_signatures belongs on all-branches.
query {
repository(owner: "{owner}", name: "{repo}") {
pullRequest(number: {PR}) {
state
mergeable
mergeStateStatus
isDraft
reviewDecision
commits(last: 1) {
nodes { commit { statusCheckRollup { state } } }
}
reviewThreads(first: 25) {
nodes { isResolved }
}
}
}
}
Required values — abort if any fail:
| Field | Must be | Abort message |
|---|---|---|
state | OPEN | "PR is not open — run /finalize-pr to fix" |
mergeable | MERGEABLE | "PR has merge conflicts — run /finalize-pr to fix" |
mergeStateStatus | CLEAN or HAS_HOOKS | "PR merge state is {value} — run /finalize-pr to fix" |
isDraft | false | "PR is a draft — mark ready first, then run /finalize-pr" |
reviewDecision | APPROVED or null | "PR needs approval — run /finalize-pr to fix" |
statusCheckRollup.state | SUCCESS | "CI is not passing: {state} — run /finalize-pr to fix" |
All reviewThreads.isResolved | true | "Unresolved review threads — run /finalize-pr to fix" |
cd ~/git/{repo}/main
git fetch origin main
git pull origin main
For remote-only branches (Renovate, Dependabot, etc.):
# NEVER use FETCH_HEAD — always create from origin/{branch}
git fetch origin {branch}
git branch {branch} origin/{branch}
Create worktree and rebase:
git worktree add ~/git/{repo}/{worktree-path} {branch}
cd ~/git/{repo}/{worktree-path}
git rebase origin/main
git log --oneline origin/main..HEAD # verify commits are ahead
git push --force-with-lease origin {branch}
gh pr checks {PR} --watch --interval 15
Do NOT proceed until all checks pass.
If force-with-lease fails on a bot branch (no upstream tracking):
git branch --set-upstream-to=origin/{branch} {branch}
git push --force-with-lease origin {branch}
cd ~/git/{repo}/main
git merge-base --is-ancestor origin/main {branch} # verify FF is possible; exit 0 = yes
git merge --ff-only {branch}
If merge-base --is-ancestor exits non-zero, main moved since rebase — go back to Step 2.
git push origin main
If rejected with "Code scanning waiting":
gh pr checks {PR} --watch --interval 15
git push origin main # retry after checks pass
Verify merged:
gh pr view {PR} --json state --jq '.state' # expect: MERGED
git worktree remove ~/git/{repo}/{worktree-path}
git branch -d {branch} # use -D only after confirming state=MERGED
git push origin --delete {branch}
git worktree prune
gh pr merge — GitHub cannot sign rebase commitsgit push --force origin main — only force-push feature branchesFETCH_HEAD — use origin/{branch}git branch -D without first confirming state=MERGED/finalize-prRebase conflicts:
# git rebase pauses and lists conflicted files
git status # see conflicted files
# edit files to resolve
git add {conflicted-files}
git rebase --continue
Push to main rejected (code scanning):
Wait for CI with gh pr checks {PR} --watch --interval 15, then retry push.
PR already merged: Skip Steps 1–6. Go directly to Step 7 cleanup.
merge-base --is-ancestor exits non-zero: Main moved while you were waiting for CI. Return to Step 2, re-sync main, re-fetch branch, re-rebase, force-push again, wait for CI, then retry merge.
Detection: git push fails, hook output shows "files were modified by this hook"
Action: Commit the auto-fixed files and retry the push:
git add -A
git commit -m "style: apply pre-push hook auto-fixes"
git push --force-with-lease origin {branch}
This commonly occurs with release-please CHANGELOG.md entries that don't conform to markdownlint rules.