finishing-a-development-branch
Wrap up finished work on a git branch - verify the tests, check for uncommitted changes, confirm the base branch, then present the integration choices (merge locally, push and open a pull request, keep as is) and carry out only the one the user picks.
- Use it when
- Implementation is done and the user asks "what now", "finish this branch", "merge this", "open a PR", "wrap this up" or "clean up the worktree". Merges, pushes, deletions and worktree removal each need the user's say-so; discarding work happens only on an explicit request. Not for starting isolated work (see using-git-worktrees), resolving conflicts, or reviewing code.
- What kind it is
- A written method: it lays out how the work is done and what to check along the way.
- Size
- 1,524 words. The whole text loads when the skill fires; only the 103-word description is always loaded.
- Starts with
- Ask for the job it describes.
How it is organised
What’s inside
The skill’s top-level sections, in order. The bar is each section’s share of the 1,524 words, so you can see where the weight sits before reading.
- 11. Look before you act151 words
- 22. Verify89 words
- 33. Confirm the base branch76 words
- 44. Present the choices93 words
- 55. Carry out the choice515 words
- 66. Clean up, only with permission293 words
- 7Never, unless the user explicitly asks42 words
- 8When you want to skip a step121 words
The skill itself
Read it before you install it
finishing-a-development-branch/SKILL.md · 1,524 wordsDownloadSkill on GitHub ↗--- name: finishing-a-development-branch description: Wrap up finished work on a git branch - verify the tests, check for uncommitted changes, confirm the base branch, then present the integration choices (merge locally, push and open a pull request, keep as is) and carry out only the one the user picks. Use when implementation is done and the user asks "what now", "finish this branch", "merge this", "open a PR", "wrap this up" or "clean up the worktree". Merges, pushes, deletions and worktree removal each need the user's say-so; discarding work happens only on an explicit request. Not for starting isolated work (see using-git-worktrees), resolving conflicts, or reviewing code. license: MIT --- # Finishing a development branch The work is written. What happens to it next, whether it is merged, published, parked or thrown away, is the user's decision. Your job is to make that decision easy and safe, then carry out exactly what they pick. Nothing in this skill merges, pushes, deletes a branch, removes a worktree or discards work until the user has chosen that specific action. A choice of one action does not authorize another: "merge it" is not permission to delete the branch, and "open a PR" is not permission to remove the worktree. ## 1. Look before you act Start read-only. ```bash git status --porcelain git branch --show-current git rev-parse --show-toplevel ``` Also record whether this is a linked worktree: compare `git rev-parse --git-dir` with `git rev-parse --git-common-dir` (each resolved to an absolute path). Capture the worktree path now, while you are still inside it. After you change directory, the same command returns the main checkout instead. **Uncommitted changes.** Merging or pushing a branch leaves them behind. Show the list and ask what to do: commit them to this branch, or leave them. If you did not make them, say so and stop for instructions. Do not stash, `git clean`, commit or discard them to get a tidy tree. **Your own debugging leftovers.** Remove temporary logging, prints and switches that you added, and only those. If you are unsure whether something is yours, ask. Do this before the final test run so the run covers the code that will ship. ## 2. Verify Run the project's full test suite on the tree you are about to integrate, after your last edit. Read the result. A green run earlier in the session proves only the tree it ran on. - If tests fail, report the failures and stop. The choices come after a green run. - If failures were already there before your work, name them and ask whether to proceed. Do not skip over them. - If the project has no tests, say that plainly. It is not the same as passing. ## 3. Confirm the base branch The base is the branch this work was cut from. Take it from the plan, the conversation or the branch's upstream. If you cannot establish it, ask: "This branch split from `<your best guess>`. Is that right?" Do not guess from `git merge-base HEAD main`; it prints a commit id, not a branch name, and returns an answer even for a branch that is not the base. Merging into the wrong base is expensive to undo. ## 4. Present the choices Offer these three and wait. Do not choose for the user, and do not add a discard option unprompted. ``` Implementation is complete and the tests pass. What would you like to do? 1. Merge into <base> locally (nothing is pushed or deleted) 2. Push the branch and open a pull request 3. Keep the branch as it is, and I will handle it later ``` If the head is detached, a local merge makes no sense. Offer only: push as a new branch and open a pull request, or keep as is. ## 5. Carry out the choice ### Option 1: merge locally Do this from the main checkout, not from inside a linked worktree. The base is usually checked out there already, and git refuses to check out a branch that another worktree holds. 1. Note the base branch's current commit, so the merge can be undone: `git rev-parse <base>`. Say it in your report. 2. Check out the base. If it tracks a remote branch, update it with `git pull --ff-only`. If the checkout or the pull fails, stop and report. Never merge from the wrong branch because a checkout failed. 3. `git merge <feature-branch>`. On conflicts, stop and bring in the user. Do not resolve silently and do not abort silently. If the user asks you to resolve them, see resolving-merge-conflicts. 4. Run the tests on the merged result. 5. If they fail, stop. Leave the branch and worktree in place and report. The merge exists only in the local base. Undoing it means moving the base back to the commit from step 1, which is a reset, so it happens only if the user asks. 6. If they pass, report, then ask about cleanup (section 6). Do not push the base branch: that is a separate request. ### Option 2: push and open a pull request Pushing publishes the branch, which is what the user chose. Use `git push -u origin <branch>`. From a detached head, name the remote branch: `git push origin HEAD:refs/heads/<new-branch>`. Open the pull request with the forge's own command-line tool if one is available, or the creation link most forges print after a push. Follow the repository's template and conventions. Write the description from the real commits and the real test results: what changed, why, how a reviewer can check it, and any decision that was not obvious. Do not state a check that was not run. Report the URL. Never force-push. A rejected push means the remote has moved: find out why. Force-push only if the user explicitly asks for it, naming the branch. Keep the worktree: review feedback gets fixed there. ### Option 3: keep as is Report the branch name, the worktree path if any, and the state of the tests. Change nothing. ### If the user asks to discard the work This path exists only for an explicit request to throw the work away. "Looks done" or "yeah, get rid of it" about something else is not one. Before anything is deleted, show exactly what will be lost: ``` This will permanently delete: - Branch <name> - Commits: <list with hashes> - Worktree at <path>, including uncommitted files: <list> Type "discard" to confirm. ``` Wait for that word. Anything else cancels, and the user can ask again. Then clean up (section 6), and force-delete the branch with `git branch -D <name>` only after the worktree is gone. Afterward the commits may be reachable from no reflog. They normally stay in the object store until git garbage-collects unreachable objects, and `git branch <name> <hash>` restores one while it is still there. Keep the hashes in your report and promise no particular window. ## 6. Clean up, only with permission After a local merge, ask before you remove anything: "Merged and the tests pass. Remove the worktree at `<path>` and delete the branch `<name>`? I will do neither unless you say so." Do each only on a yes. A confirmed discard has already covered the items its confirmation listed, and nothing beyond them. Rules for removal: - **Only a worktree you created.** A directory name such as `.worktrees/` does not prove ownership. If you did not make it, or the host manages it, leave it in place, and use the host's own exit feature only in a mode that keeps it. - **Run it from outside the worktree**, in the main checkout, using the path you captured. - **Use `git worktree remove <path>` without `--force`.** It refuses when there are modified or untracked files, which means files that exist nowhere else. Show them and ask: commit them to the branch first, move them somewhere safe, or lose them. Use `--force` only with the user's say-so for those exact files. - **Ignored files go silently.** Git deletes ignored files, such as a `.env` or a local database, along with the worktree and gives no warning. Run `git status --porcelain --ignored` first and show what would vanish. - **Order matters.** Remove the worktree, then delete the branch. Git refuses to delete a branch a worktree still has checked out. - **Use the safe delete, `git branch -d`, for a merged branch.** It refuses an unmerged one. `-D` is for confirmed discards only. - **Do not run `git worktree prune` as part of cleanup.** `remove` clears its own record, and pruning also drops the records of other worktrees whose folders are merely missing right now. - **Do not delete remote branches.** That is its own request. ## Never, unless the user explicitly asks Force-push. `git reset --hard`. Merge with a failing or unrun test suite. Merge while the working tree has uncommitted changes. Skip hooks with `--no-verify`. Delete a branch, a worktree or a remote branch. Stash, clean or discard changes you did not make. ## When you want to skip a step | The thought | The answer | |---|---| | "They obviously want it merged." | Present the choices and wait. | | "The tests passed earlier." | Run them on the tree you are integrating. | | "The base is obviously main." | Confirm it. | | "The PR is up, so I can remove the worktree." | Feedback gets fixed there. Keep it until the work lands. | | "That other worktree looks stale." | It is not yours. Leave it. | | "Removal was refused, so I will force it." | The refusal is the safeguard. Show the files and ask. | | "The merged result fails, but it is probably flaky." | Stop. Leave everything in place. |
The second audit
What we found in the sources
It keeps the shape of the version the others copy (obra/superpowers: verify, detect the environment, confirm the base, present a fixed set of choices, execute only the chosen one, clean up from outside the worktree) and tightens it so that merging, pushing, deleting and removing a worktree each need the user's say-so, with discard only on an explicit request. The git behaviours it states were checked in a scratch repository on git 2.50.1 (Apple Git-155); the skill itself has not been run against real tasks. Every source below was read at the commit the auditor recorded. Nothing was taken from a source without a permissive license.
What each source contributed
- obra/superpowers ↗ · Primary basis · MIT
The sequence verify then detect then confirm the base then present the choices; a menu of three options (two on a detached head) with discard held back for an explicit request; the typed 'discard' confirmation; merge before removing anything; keeping the worktree after a pull request; capturing the worktree path before changing directory and removing from outside it; cleaning only worktrees the skill made; and the rationalizations table, cut to seven rows. Most other English sources here read as older shapes, ports or condensed rewrites of it.
- lsy041015/orchestra ↗ · Added ideas · MIT
Check for uncommitted work before the menu; `git pull --ff-only`; stop at the first failed step so a merge never lands on the wrong branch; list ignored files before a worktree is removed because removal deletes them silently; never `--force` on the agent's own initiative and ask what to do with the files when removal is refused; no `git worktree prune` as part of cleanup; directory names do not prove ownership.
- RollRollRoll/agent-toolkit ↗ · Added ideas · Apache-2.0
A read-only state check first; stop and ask if changes that are not the agent's are present; remove only the agent's own debugging leftovers and do it before the final test run; no automatic stash, git clean or silent discard; and each of commit, merge, push, pull request, branch deletion and worktree removal needs its own confirmation, because choosing merge does not authorize removing the worktree. Read in Chinese.
- rizukirr/vibekit ↗ · Added ideas · MIT
A choice authorizes only that action; merging locally neither pushes nor deletes the branch; never force-push, delete a remote branch, merge with a dirty working tree or skip hooks without being asked; on a merge conflict stop and leave it for the user.
- yimwoo/hotl-plugin ↗ · Added ideas · MIT
Guardrails: do not merge just because the tests passed, do not create a pull request unless that was the choice, do not delete without explicit confirmation, and leave the checkout intact on a merge conflict.
- brunob54/superpowers-orchestrator ↗ · Added ideas · MIT
The contents of a good pull request description: what changed, why, how a reviewer can verify it, and the non-obvious decisions.
- jason-chen-coder/dev-skills ↗ · Added ideas · MIT
Ask what to do with uncommitted changes before a merge or pull request, leave branches, stashes and worktrees nobody confirmed alone, and ask when the owner of a workspace cannot be determined. The body mixes Chinese and English and was read as such.
- toruai/toru-claude-agents ↗ · Added ideas · MIT
When there are no tests or checks, say so explicitly instead of reporting a pass. The rest of that skill is a different job (session close-out) and was not used.
What changed
- The description now names the choices, lists the phrases that should trigger it ("finish this branch", "merge this", "open a PR", "clean up the worktree") and says merges, pushes, deletions and worktree removal each need the user's say-so. The upstream description is only "Use when implementation is complete, all tests pass, and you need to decide how to integrate the work".
- Merging locally no longer deletes the branch and removes the worktree as part of the same choice. Upstream does both once the merge is green without a separate question. The menu line says nothing is pushed or deleted, and cleanup is asked about afterwards. Two sources (RollRollRoll, vibekit) make a similar separation.
- `git pull` became `git pull --ff-only`, and a failed checkout or pull stops the merge.
- The base branch's commit is noted before merging, and the failure path says undoing a local merge means moving the base branch back, which is a reset and waits for the user. Upstream says only that the merge is 'local and recoverable'.
- Added an uncommitted-changes check, removal of the agent's own debugging leftovers before the final test run, pre-existing failures reported by name, and a statement for the no-tests case.
- Cleanup rules now include listing ignored files before removal and not using `git worktree prune`. Removal ordering (worktree, then branch) is kept from upstream and confirmed: git refused to delete a branch that a worktree still had checked out in a scratch repository on git 2.50.1 (Apple Git-155).
- The discard confirmation lists uncommitted files as well as commits, and notes that after the worktree and branch are gone the commits may sit in no reflog but the object can be restored by hash until git garbage-collects it. No time window is promised.
- Added an explicit never-without-being-asked list (force-push, reset --hard, merge with a failing suite or dirty tree, --no-verify, deleting branches, worktrees or remote branches, stashing or cleaning changes that are not the agent's).
- Removed 'Announce at start' and 'your human partner', and wrote the pull request step for any forge: its own command-line tool if there is one, otherwise the creation link.
Problems found in the sources
- obra/superpowers: Choosing 'merge locally' also deletes the branch (`git branch -d`) and removes the worktree after a green run, and the menu text does not say so. `git pull` is plain, which can create a merge commit or conflict in the base. Cleanup runs `git worktree remove` then `git worktree prune`; removal deletes ignored files in the worktree (such as a .env) without a warning, and removing a worktree that held an ignored .env succeeded silently in a scratch repository on git 2.50.1 (Apple Git-155). Ownership is decided by whether the path is under .worktrees/ or worktrees/, which does not show who created it. A failing merged result is called 'local and recoverable' without saying how. It uses 'your human partner' and 'Announce at start'.
- lsy041015/orchestra: The strongest on cleanup safety: lists ignored files before removal, refuses `--force`, asks what to do with files that exist nowhere else, and avoids `git worktree prune`. It is tied to an orchestra-owned-worktree marker file, a .orchestra/ records directory, an orchestra:verification-before-completion reference, Codex workers and one host's ExitWorktree tool, and its Step 6 shell block is long.
- RollRollRoll/agent-toolkit: Strong on authorization (each state change needs its own confirmation) and on ordering cleanup before the final test. It gives no commands for the merge or the removal, lists discard among its options, and describes itself as a unit of 'agent-toolkit' with a calling contract for other skills. Chinese throughout.
- rizukirr/vibekit: Tied to its own pipeline: it runs only after a review-pack 'yes' and a verify-gate 'ready', and uses vibe/<slug> branches and spec and plan paths. Its abandon option is in the menu. It says commits stay 'reachable for ~90 days via reflog' after the branch is deleted; after removing the worktree and force-deleting the branch in a scratch repository on git 2.50.1 (Apple Git-155), no reflog listed the commit, though the object still existed and `git branch <name> <hash>` restored it. Its rule 'never reset --hard on main / master / the base branch' leaves other branches unaddressed (unclear whether that is a choice).
- yimwoo/hotl-plugin: Depends on a run runtime (hotl-rt summary, action begin and complete, owner tokens) and a helper script that are not in the file, so a lone copy cannot execute. The guardrails section is portable.
- brunob54/superpowers-orchestrator: The description opens 'MUST USE' and says it is routed by using-superpowers or executing-plans, neither in the file. Its triggers include 'squash and merge' but there is no squash option. Option 1 lists 'Delete merged branch' before 'Remove worktree', an order git refuses while the worktree still has the branch checked out (verified in a scratch repository on git 2.50.1 (Apple Git-155)). The pull request step reads a session-log.md the skill does not define. It deletes and removes after a merge without a further question.
- jason-chen-coder/dev-skills: Refers to references/dev-baseline.md, a dev-verify and a dev-code-review skill and ../../docs/multi-agent-policy.md, none in the file. Mixes Chinese and English. Determines the base with `git merge-base HEAD main`, which prints a commit id and not a branch name. It lists no commands for the merge itself or for cleanup.
- toruai/toru-claude-agents: A different job: closing a work session. It delegates review to named personas (Bob, Garry, Arlo), saves learnings through a memory tool, and keeps state under ~/.claude/dev-cycles/. It tells the agent to add no Co-Authored-By lines or AI attribution to commits, which is a repository policy stated as an absolute. It deletes the review diff files it made and hard-codes `main` in `git diff main...HEAD`.
- mzored/superpowers-cc-to-codex: A HARD-GATE requires an MCP tool call (codex_branch_analysis) before any option is shown, so the skill cannot run without that tool. It removes the worktree after a pull request is opened (Options 1, 2 and 4), though the user needs it for review feedback. Its discard path runs `git checkout <base>` then `git branch -D` before removing the worktree; from a linked worktree the checkout is refused when the base is checked out in the main checkout, and the branch delete is refused while the worktree exists (both verified in a scratch repository on git 2.50.1 (Apple Git-155)).
- thepragmaticbear/bearpaws: Condensed and wrapped in custom XML-like tags with bp: namespaced references. Discard runs 'checkout base, force-delete the branch, remove the worktree', an order git refuses while the worktree holds the branch (verified in a scratch repository on git 2.50.1 (Apple Git-155)). It removes the worktree after a pull request is opened.
- gylove1994/superpowers-deepseek-v4: Puts 'Discard this work' in the menu as a fourth option, hard-codes `gh pr create` with a body template, and runs `git worktree prune` after removal. Otherwise it follows the upstream text closely.
- leodorareluctant259/superpowers-zh: Contradicts itself on cleanup: Step 5 removes the worktree for Options 1, 2 and 4, while its quick-reference table, Common Mistakes and Red Flags say to clean up only for Options 1 and 4 and keep the worktree for a pull request.
What was dropped
- Product-specific machinery: hotl-rt, HOTL_OWNER_TOKEN and scripts/hotl-finish-execution.sh (hotl-plugin); the orchestra ownership marker file and .orchestra archive step; vibekit's review-pack and verify-gate chain and vibe/<slug> branch names; the Codex branch-analysis gate (mzored); toruai's named reviewer personas, memory tool and session files.
- Discard as a menu option. It is available only when the user asks for it.
- `git worktree prune` after removal, and the hard-coded `gh pr create` with a fixed body template.
- vibekit's statement that abandoned commits stay reachable for about 90 days through the reflog, which did not hold in the scratch test, and its 'Nothing else' output compression policy.
- toruai's instruction to add no Co-Authored-By lines or AI attribution to commits. That is a repository or user policy, which this skill leaves to the user.
Read but not used (5)
- jnmetacode/superpowers-zh: A Chinese translation of the current obra/superpowers text: the three-option menu, the environment table, the cleanup rules and the rationalizations table match as far as they were compared. Adds version and hermes tag metadata. Nothing used beyond upstream.
- leodorareluctant259/superpowers-zh: A Chinese translation of an older shape of the upstream text: four options including discard, a plain `git pull`, and a Common Mistakes section. Nothing used.
- gylove1994/superpowers-deepseek-v4: A variant of upstream with a four-option menu that includes discard, and a Common Mistakes and Red Flags section in place of the rationalizations table. Nothing used beyond upstream.
- mzored/superpowers-cc-to-codex: A port that gates the finish on a Codex-backed analysis tool, for explicit invocation only (it sets disable-model-invocation). The finish steps themselves are the older upstream shape. Nothing used.
- thepragmaticbear/bearpaws: A condensed XML-tagged rewrite of the older upstream shape with four options. Nothing used.
Left out for license (3)
No license is declared on these, so nothing was taken from them: Fintama/swisper-superpowers, Athyrr/aikit, Itzalive/resistance-ai.
Same text, wherever you work
Use it where you work
Copy the folder into your skills directory, then ask for the job or type its start command.
- Download
SKILL.mdwith the button above, and put it in a folder namedfinishing-a-development-branch. - Zip the folder.
- In Claude, open Settings → Skills and upload the zip.
SKILL.md is plain Markdown. Copy the text and paste it as the system prompt or the first message. It will not trigger by itself there; you start it.