/landpr
Input
- •PR: $1 (number or URL). If missing: use most recent PR in convo; if ambiguous: ask.
Goal
- •End state: GitHub PR state =
MERGED(neverCLOSED).
- •Guardrails
- •
git status -sbclean (no local changes). - •If PR is draft, has conflicts, or you can’t push to head branch: stop + ask.
- •Prefer repo default branch as base (often
main).
- •Capture PR context
sh
PR="$1"
gh pr view "$PR" --json number,title,state,isDraft,mergeable,author,baseRefName,headRefName,headRepository,maintainerCanModify --jq '{number,title,state,isDraft,mergeable,author:.author.login,base:.baseRefName,head:.headRefName,headRepo:.headRepository.nameWithOwner,maintainerCanModify}'
prnum=$(gh pr view "$PR" --json number --jq .number)
contrib=$(gh pr view "$PR" --json author --jq .author.login)
base=$(gh pr view "$PR" --json baseRefName --jq .baseRefName)
head=$(gh pr view "$PR" --json headRefName --jq .headRefName)
head_repo_url=$(gh pr view "$PR" --json headRepository --jq .headRepository.url)
- •Update base + create temp branch
sh
git checkout "$base" git pull --ff-only git checkout -b "temp/landpr-$prnum"
- •Checkout PR + rebase onto temp
sh
gh pr checkout "$PR" git rebase "temp/landpr-$prnum"
- •Changelog
- •Update
CHANGELOG.md: include#$prnum+ thanks@$contrib. - •All code changes and tests should already be complete from prior review steps.
- •Gate (before commit)
- •Run full repo gate (lint/typecheck/tests/docs). Prefer a single
pnpm checkif the repo defines it (for example, OpenClaw:pnpm checkrunspnpm tsgo && pnpm lint && pnpm format). Otherwise:pnpm lint && pnpm build && pnpm test.
- •Commit (via
committer)
sh
committer "fix: <summary> (#$prnum) (thanks @$contrib)" CHANGELOG.md <changed files> land_sha=$(git rev-parse HEAD)
- •Push rebased PR branch (fork-safe)
sh
git remote add prhead "$head_repo_url.git" 2>/dev/null || git remote set-url prhead "$head_repo_url.git" git push --force-with-lease prhead "HEAD:$head"
- •Verify mergeable (abort if conflicts)
sh
mergeable=$(gh pr view "$PR" --json mergeable --jq .mergeable) if [ "$mergeable" != "MERGEABLE" ]; then echo "PR not mergeable ($mergeable). Base may have changed. Re-run land-pr." exit 1 fi
- •Merge PR
- •Rebase:
gh pr merge "$PR" --rebase - •Squash:
gh pr merge "$PR" --squash - •Never
gh pr close.
- •Sync base locally
sh
git checkout "$base" git pull --ff-only
- •Comment with SHAs + thanks
sh
merge_sha=$(gh pr view "$PR" --json mergeCommit --jq '.mergeCommit.oid') gh pr comment "$PR" --body "Landed via temp rebase onto $base. - Gate: <cmds> - Land commit: $land_sha - Merge commit: $merge_sha Thanks @$contrib!"
- •Verify state ==
MERGED
sh
gh pr view "$PR" --json state,mergedAt --jq '.state + \" @ \" + .mergedAt'
- •Cleanup
sh
git branch -D "temp/landpr-$prnum"