---
title: "Finish a development branch: review, setup & limitations · Undominated.ai"
canonical: https://undominated.ai/skills/obra-finishing-a-development-branch/
description: "After a green test suite, show a fixed integration menu and run only the option the person chooses."
---

# Finish a development branch: review, setup & limitations · Undominated.ai

> After a green test suite, show a fixed integration menu and run only the option the person chooses.

[← Explore all skills](/skills/)

GIT WORKFLOW / Jesse Vincent

# Finish a development branch

After a green test suite, show a fixed integration menu and run only the option the person chooses.

 [See setup guidance ↓](#setup)[Original source ↗](https://github.com/obra/superpowers/tree/8ca22dba9a94f28898bbce59f2537ff4d87c747d/skills/finishing-a-development-branch)

SOURCE REVIEW

 Reviewed 2026-10-14
 Evidence 3 linked sources
 Publisher Jesse Vincent
 Licence [MIT ↗](https://github.com/obra/superpowers/blob/8ca22dba9a94f28898bbce59f2537ff4d87c747d/LICENSE)
 Revision 8ca22dba9a94
 [Read what was—and wasn’t—checked ↓](#review)

“Use when implementation is complete, all tests pass, and you need to decide how to integrate the work”

 [Jesse Vincent · upstream description ↗](https://github.com/obra/superpowers/blob/8ca22dba9a94f28898bbce59f2537ff4d87c747d/skills/finishing-a-development-branch/SKILL.md) Our analysis follows below.

01 / THE REASONING

## Why this made the selection.

 - The skill stops when tests fail, then waits for one of three written options before merge, push, or leaving the branch alone.
- Deleting the branch requires the typed word discard, and a refused worktree removal must not be forced.

### A good fit for

 - Closing a finished branch when a person must choose merge, pull request, or leave-it before any git write.
- Preserve host-managed or detached workspaces while choosing a supported integration path

### Weigh up before choosing

 - Option 1 runs checkout, pull, and merge, then deletes the branch only after the merged suite is green. Option 2 pushes. Discard force-deletes the branch.
- Sibling skills in obra/superpowers were not opened. A repository-wide install would add them. The installer was not executed. Reading the file is not a run of the procedure.
- Directory naming is only a heuristic for worktree ownership; confirm actual provenance before cleanup. Avoid reusing the special GIT_DIR environment name in an implementation of the sample detection commands.
- A failed test run on the merged result stops cleanup and preserves the branch and worktree for investigation.

02 / THE REVIEW RECORD

## What we actually inspected.

Source review has boundaries. A clear record is more useful than a “safe” badge.

### Material inspected

 - SKILL.md in full at the pinned commit
- MIT licence at the same commit

### Our findings

 - Copyright (c) 2025 Jesse Vincent. The directory has no other files.
- Force-push is allowed only after an explicit request when a push is rejected. Cleanup is limited to worktrees under .worktrees/ or worktrees/.
- The source distinguishes normal, named-worktree and detached states, preserves host-managed workspaces and PR worktrees, and stops cleanup when uncommitted files or failed merged tests remain.
- The normal menu is merge locally, push and create a PR, or keep the branch; the base branch is confirmed before a merge.

### Not established by this review

 - Running the test-suite or git commands
- The Skills CLI installer
- The other Superpowers skills
- Not executed: it was not installed or run.

The review applies to the material and revision named here. A newer upstream release can change its behavior.

03 / PUT IT TO WORK

## Add a skill to your workflow.

[Upstream setup instructions ↗](https://github.com/vercel-labs/skills/blob/48dc9e8eb8aa19040e91cb90ba0b642c9cbad57e/README.md)

DOCUMENTED COMMAND

 npx skills add obra/superpowers/skills/finishing-a-development-branch Copy command ↗

Run in your terminal to choose your AI tools, project or global scope, and installation method. This short command follows the current upstream version; the review covers the revision shown above.

 Optional: install the reviewed revision

Keeps the original source and installer version where recorded, while leaving your AI tools and installation scope for you to choose.

 npx skills add https://github.com/obra/superpowers/tree/8ca22dba9a94f28898bbce59f2537ff4d87c747d/skills/finishing-a-development-branch Copy reviewed-revision command ↗ - The command pins only this skill at the reviewed commit. The installer was not executed.
- Do not use a global yes-to-all install of the repository. That would install skills this review did not select.
- For manual installation instead, download the complete bundle from https://undominated.ai/resources/skills/obra-finishing-a-development-branch/bundle.zip and extract it into a new directory. It holds SKILL.md unchanged at revision 8ca22dba, the upstream licence and an attribution file.
- Place the extracted directory in your host's documented skills directory, named finishing-a-development-branch. Keep SKILL.md and the licence together.

### Before you start

 - Node.js and npm
- A git checkout whose tests you are willing to run

### Compatibility

Agent Skills hosts · Git

### Implementation

Markdown

### Workflow prompt. Git writes wait for a menu choice or the typed word discard.

 - Run the project test suite
- Git read, and git write only after the stated confirmation
- Merge/pull/push and branch/worktree removal are explicit integration actions with separate consequences; a rejected removal must not be bypassed by force.

### Cost model

MIT instructions at no charge. Copyright (c) 2025 Jesse Vincent.

THE COMPLETE REVIEWED DEFINITION

## Read it before you reuse it.

Original source bytes, with attribution. Review the host-specific setup notes above.

 Copy definition ↗ [Download definition + licence ↗](/resources/skills/obra-finishing-a-development-branch/bundle.zip)[Raw Markdown ↗](/resources/skills/obra-finishing-a-development-branch/definition.md)
 ---
name: finishing-a-development-branch
description: Use when implementation is complete, all tests pass, and you need to decide how to integrate the work
---

# Finishing a Development Branch

## Overview

**Core principle:** Verify tests → Detect environment → Present options → Execute choice → Clean up.

**Announce at start:** "I'm using the finishing-a-development-branch skill to complete this work."

## Step 1: Verify Tests

Run the project's full test suite (`npm test` / `cargo test` / `pytest` / `go test ./...`).

**If tests fail**, report the failures and stop — the menu comes after a green suite:

```
Tests failing (<N> failures). Must fix before completing:

[Show failures]
```

**If tests pass:** continue to Step 2.

## Step 2: Detect Environment

```bash
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
# Capture now, while still inside the workspace — Step 5 changes directory
# before cleanup (Step 6) needs this value
WORKTREE_PATH=$(git rev-parse --show-toplevel)
```

This determines which menu to show and how cleanup works:

| State | Menu | Cleanup |
|-------|------|---------|
| `GIT_DIR == GIT_COMMON` (normal repo) | Standard 3 options | No worktree to clean up |
| `GIT_DIR != GIT_COMMON`, named branch | Standard 3 options | Provenance-based (see Step 6) |
| `GIT_DIR != GIT_COMMON`, detached HEAD | Reduced 2 options (no merge) | Externally managed — leave in place |

## Step 3: Determine Base Branch

The base branch is whatever this work forked from — usually named in the
plan, the conversation, or the branch's upstream. If it is not already
known, ask: "This branch split from <your best guess> - is that correct?"
Confirm before merging: merging into the wrong base is expensive to undo.

## Step 4: Present Options

**Normal repo and named-branch worktree — present exactly these 3 options:**

```
Implementation complete. What would you like to do?

1. Merge back to <base-branch> locally
2. Push and create a Pull Request
3. Keep the branch as-is (I'll handle it later)

Which option?
```

**Detached HEAD — present exactly these 2 options:**

```
Implementation complete. You're on a detached HEAD (externally managed workspace).

1. Push as new branch and create a Pull Request
2. Keep as-is (I'll handle it later)

Which option?
```

Present the menu exactly as written — concise, with every option coming
from the list above. Discarding the work happens only in response to your
human partner explicitly asking for it (see "If your human partner asks to
discard the work" below). Wait for their answer; the integration decision
is theirs.

## Step 5: Execute Choice

### Option 1: Merge Locally

```bash
# Get main repo root for CWD safety
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
cd "$MAIN_ROOT"

# Merge first — verify success before removing anything
git checkout <base-branch>
git pull
git merge <feature-branch>

# Verify tests on merged result
<test command>
```

If tests fail on the merged result: stop, leave the worktree and branch in
place, and investigate — nothing has been pushed, so the merge is local
and recoverable.

Once the merged result is green: clean up the worktree (Step 6), then
delete the branch:

```bash
git branch -d <feature-branch>
```

### Option 2: Push and Create PR

```bash
git push -u origin <feature-branch>
# From a detached HEAD, name the new branch on the remote:
# git push origin HEAD:refs/heads/<new-branch>
```

Then create the pull/merge request against <base-branch> with the forge's
tooling — its CLI if one is available, or the creation URL most forges
print when you push — following the repo's PR template and conventions if
present, and report the URL to your human partner.

Keep the worktree — your human partner iterates on PR feedback there.

### Option 3: Keep As-Is

Report: "Keeping branch <name>. Worktree preserved at <path>."

### If your human partner asks to discard the work

This path exists only as a response to an explicit request to throw the
work away. Confirm first:

```
This will permanently delete:
- Branch <name>
- All commits: <commit-list>
- Worktree at <path>

Type 'discard' to confirm.
```

Wait for that exact confirmation. When it arrives:

```bash
MAIN_ROOT=$(git -C "$(git rev-parse --git-common-dir)/.." rev-parse --show-toplevel)
cd "$MAIN_ROOT"
```

Then clean up the worktree (Step 6) and force-delete the branch:

```bash
git branch -D <feature-branch>
```

## Step 6: Cleanup Workspace

**Runs for Option 1 and confirmed discards.** Options 2 and 3 always
preserve the worktree. Both callers have already changed directory to the
main repo root — worktree removal must run from outside the worktree —
and use the `GIT_DIR`/`GIT_COMMON`/`WORKTREE_PATH` values captured in
Step 2, from before that directory change.

**If `GIT_DIR == GIT_COMMON`:** Normal repo, no worktree to clean up. Done.

**If `WORKTREE_PATH` is under `.worktrees/` or `worktrees/`:** Superpowers
created this worktree — we own cleanup:

```bash
git worktree remove "$WORKTREE_PATH"
git worktree prune # Self-healing: clean up any stale registrations
```

**If removal is refused** (`contains modified or untracked files`): the
worktree holds files that exist nowhere else — uncommitted plans, notes,
or scratch work. Never `--force` on your own initiative. Show your human
partner what is at stake and ask:

```bash
git -C "$WORKTREE_PATH" status --porcelain -uall
```

```
Worktree removal refused — these files were never committed:

<file list>

1. Commit them to <branch> before cleanup
2. Move them into <main repo root>
3. Delete them (unrecoverable)

Which?
```

Carry out the choice, then remove the worktree.

**Otherwise:** The host environment owns this workspace — leave it in
place. If your platform provides a workspace-exit tool, use it.

## Quick Reference

| Option | Merge | Push | Keep Worktree | Cleanup Branch |
|--------|-------|------|---------------|----------------|
| 1. Merge locally | yes | - | - | yes |
| 2. Create PR | - | yes | yes | - |
| 3. Keep as-is | - | - | yes | - |
| Discard (explicit request only) | - | - | - | yes (force) |

## Common Rationalizations

| Excuse | Reality |
|--------|---------|
| "Tests passed earlier this session" | Run the suite on the tree you are about to integrate. A green run only proves the tree it ran on. |
| "They obviously want it merged" | Integration is your human partner's decision. Present the menu and wait. |
| "They seem done with this feature — I'll offer to discard it" | The menu is complete as written. Discard happens only when your human partner asks for it in so many words. |
| "'Yeah, get rid of it' counts as confirmation" | Only the typed word `discard` authorizes deletion. |
| "The PR is up, so the worktree is clutter now" | PR feedback gets fixed in that worktree. It stays until the work lands. |
| "This other worktree looks stale — I'll clean it too" | Clean up only worktrees under `.worktrees/` or `worktrees/`. Everything else belongs to the host. |
| "Removal refused — `--force` is just finishing the cleanup" | The refusal means files exist only in that worktree. `--force` destroys them permanently. Show your human partner and ask. |
| "The merged-result failure is probably flaky" | A failing merged result stops everything. Branch and worktree stay put while you investigate. |
| "The base branch is obviously main" | Confirm the fork point or ask. Merging into the wrong base is expensive to undo. |
| "The push was rejected — force-push will fix it" | A rejected push means the remote moved. Investigate; force-push only on your human partner's explicit request. |

The download contains SKILL.md . Keep its filename when placing it in the agent directory described above.

By **Jesse Vincent**. [Exact upstream source ↗](https://github.com/obra/superpowers/blob/8ca22dba9a94f28898bbce59f2537ff4d87c747d/skills/finishing-a-development-branch/SKILL.md) · [Licence](/resources/skills/obra-finishing-a-development-branch/LICENSE.txt) · [Attribution](/resources/skills/obra-finishing-a-development-branch/ATTRIBUTION.txt)

SHA-256 8db5a922b242dd4e1bf824cb91c13b3e8d8e8a86d6ceaf7f0774eb9cce909d65

 Read the applicable licence MIT License

Copyright (c) 2025 Jesse Vincent

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

04 / FOLLOW THE EVIDENCE

## The source trail.

Our notes are separate from the original resource. Check upstream before adopting a new version.

 - [Finishing a development branch ↗](https://github.com/obra/superpowers/blob/8ca22dba9a94f28898bbce59f2537ff4d87c747d/skills/finishing-a-development-branch/SKILL.md) Checked 2026-10-14 https://github.com/obra/superpowers/blob/8ca22dba9a94f28898bbce59f2537ff4d87c747d/skills/finishing-a-development-branch/SKILL.md Supports: Menu before merge or push, Typed discard before force-delete
- [MIT licence ↗](https://github.com/obra/superpowers/blob/8ca22dba9a94f28898bbce59f2537ff4d87c747d/LICENSE) Checked 2026-10-07 https://github.com/obra/superpowers/blob/8ca22dba9a94f28898bbce59f2537ff4d87c747d/LICENSE Supports: Copyright (c) 2025 Jesse Vincent, Redistribution with attribution
- [Pinned source review C2-W15 ↗](https://raw.githubusercontent.com/obra/superpowers/8ca22dba9a94f28898bbce59f2537ff4d87c747d/skills/finishing-a-development-branch/SKILL.md) Checked 2026-10-15 https://raw.githubusercontent.com/obra/superpowers/8ca22dba9a94f28898bbce59f2537ff4d87c747d/skills/finishing-a-development-branch/SKILL.md Supports: limitations, review.notTested

KEEP COMPARING

## Other approaches to consider.

Related by category or shared topics. These are alternatives to inspect, not a measured quality order.

 [### PR improver ↗ Pins the branch loop that refuses the base branch, stops on an empty diff, will not replace a missing reviewer, and does not commit.](/skills/trailofbits-pr-improver/)[### Code improver ↗ Pins the generic review loop that will not choose a reviewer, will not start on an unconfirmed scope, and will not commit.](/skills/trailofbits-code-improver/)[### Conventional Branch ↗ Creates and validates Git branches against the Conventional Branch specification — feature/, bugfix/, hotfix/, release/, chore/ — with a validation ruleset, an invalid-example table, trunk detection and a mapping to Conventional Commits.](/skills/github-conventional-branch/)

 [AI Tools ↗](/tools/)[Skills ↗](/skills/)[Agents ↗](/agents/)[MCP Servers ↗](/mcp-servers/)[Workflows ↗](/workflows/)

## Continue your investigation

 - [Choose a toolkit](/tools/)
- [Inspect execution hosts](/agents/)
- [Check tool access](/mcp-servers/)
- [Check project dependencies](/check-repo/)
