"All tests pass" isn't done. A branch lands cleanly only if the diff is the diff you meant, main hasn't drifted under you, and the integration path matches the project's conventions. LingCode walks the closing checklist — and tells you when the right answer is "throw this away."
The naïve finish is: tests pass locally, push, open PR, done. Four things commonly go wrong between green tests and a clean merge:
The skill in this tutorial gives LingCode an explicit closing protocol: audit the diff, sync with main, choose the integration path, and bail cleanly if the work doesn't deserve to ship.
git log main.Before doing anything else, have LingCode compare what's in the branch against what the branch was supposed to do:
Compare the branch diff against the original task. Run:
- git diff main...HEAD
- git log main..HEAD --oneline
For each change, classify:
- IN-SCOPE: matches the stated task.
- DRIVE-BY: small unrelated fix or cleanup.
- ACCIDENTAL: stray prints, commented-out code, dead imports,
unrelated formatting churn.
Flag anything ACCIDENTAL for removal. Flag DRIVE-BY for a
decision — keep, split into a separate branch, or revert.
Accidental changes are the cheapest review comments to avoid. Drive-by fixes are a judgment call — small ones ride along, real refactors deserve their own PR so the next person reading git log understands why.
Local green doesn't mean integrated green. Have LingCode bring main into the branch — whichever way your repo prefers — and re-run the suite:
1. git fetch origin
2. If the repo rebases: git rebase origin/main
If the repo merges: git merge origin/main
(Infer from `git log --merges main | head` — if main has merge
commits, this repo merges; if it's a flat line, it rebases.)
3. Resolve conflicts. For each conflict, explain in 1-2 lines what
the conflict is and how you resolved it.
4. Re-run the full test suite — not just the affected file.
This is where the "I'm done" claim becomes verifiable. Ask LingCode to run a fixed checklist and report PASS/FAIL on each item:
Run the closing checklist. For each item, report PASS / FAIL /
N/A with one-line evidence:
- Tests pass: full suite, post-rebase.
- Linter clean: project's linter, not just LingCode's opinion.
- Type-check clean: tsc / mypy / xcodebuild / etc.
- No console.log / dbg! / print() debug noise.
- No commented-out code.
- No TODO that should have been done in this branch.
- Diff matches the intent — re-run the IN-SCOPE / ACCIDENTAL
classification on the post-rebase diff.
- Commit messages are imperative ("Add X", "Fix Y"), no WIP,
no fixup commits.
- If the repo squashes: the PR title will be the merge commit
message — does it say what changed?
Stop on first FAIL. Don't proceed to merge with anything red.
"Stop on first FAIL" is the rule. The temptation to merge with a warning suppressed is how broken branches land.
Three sensible paths out of a finished branch. Pick deliberately:
gh pr create.Ask LingCode to recommend one based on the repo's history:
Recommend the integration path. Consider:
- Does main accept direct pushes from this user / role?
- Does the repo require PRs (branch protection)?
- Is this a single-author repo or a team?
- Is the change risky (logic) or trivial (typo)?
Then propose one path with a one-line justification.
If the path is PR, the description should match what the patch actually does — not what you set out to do at the start of the branch. Have LingCode draft from the final diff, not the original task:
Draft the PR body from the post-rebase diff, not from the
original task description. Structure:
## Summary
1-3 bullets of what changed in the codebase, in plain language.
## Why
The user-visible reason or the problem this fixes. One paragraph.
## Test plan
Bulleted checklist of how to verify. Include the exact commands
you ran locally.
## Risk
What could go wrong, if anything? Migration steps? Config flags?
"N/A" if genuinely none.
Title: imperative, under 70 characters, no trailing punctuation.
The "Why" section is the one people skip and the one reviewers actually need. Why now, why this approach, why not the obvious alternative.
Sometimes the right answer is throwing the branch away. The skill teaches LingCode to recognize the signals and propose it explicitly rather than push through:
Recommend SCRAP if any of these hold:
- The branch tried an approach the codebase clearly resists
(the diff fights existing abstractions in >3 files).
- A simpler approach became obvious mid-way and the branch
is now legacy thinking.
- The feature was speculatively built and product changed
direction.
- Tests pass but the code is structurally bad and rewriting
is cheaper than refactoring.
If recommending SCRAP, identify what's worth salvaging:
- Any tests written? They probably encode useful behavior.
- Any docstrings or comments capturing decisions?
- Any small utility extractions?
Land the salvage as a tiny PR. Then delete the branch.
Scrapping a branch with a clean salvage PR is not failure — it's the cheapest way to capture what the branch learned without inheriting its mistakes.
The closing checklist isn't complete until the branch is gone. Ask LingCode to clean up:
After merge:
- git checkout main
- git pull origin main
- git branch -d <branch-name> # local
- git push origin --delete <branch> # remote, if not auto-deleted
If `git branch -d` refuses because the branch isn't merged
(common with squash-merge), verify the squashed commit is in
main, then use `-D`. Don't `-D` without verification.
Stale branches are how the next "where did that experiment go?" investigation starts six months later.
The closing protocol is packaged as a skill — drop it into your skills folder and ask LingCode to "finish this branch" once tests are green:
---
name: finishing-a-development-branch
description: Use when implementation is complete, all tests pass, and you need to decide how to integrate the work. Triggers: 'tests pass, what now', 'wrap up this branch', 'merge vs PR', 'finish up', 'close this out', 'I'm done coding', 'ship it'. Actions: diff audit (IN-SCOPE/DRIVE-BY/ACCIDENTAL), sync with main, run closing checklist, choose integration path (PR / direct push / scrap), post-merge branch cleanup. Output: clean commit history + clear next step (PR opened, merge done, or branch deleted).
---
Walk a finished feature branch to a clean integration. Green
tests are not done; the branch still needs to land.
1. Audit the diff against intent. Classify each change as
IN-SCOPE / DRIVE-BY / ACCIDENTAL. Strip ACCIDENTAL.
2. Sync with main. Rebase or merge based on the repo's
convention (infer from git log). Resolve conflicts and
re-run the full test suite.
3. Run the closing checklist: tests, lint, type-check, no
debug noise, no commented-out code, commit messages clean,
diff matches intent. Stop on first FAIL.
4. Pick an integration path: PR, direct push, or SCRAP. Justify
in one line based on repo history and risk.
5. If PR: draft the body from the post-rebase diff (not the
original task). Summary + Why + Test plan + Risk.
Imperative title under 70 chars.
6. If SCRAP: identify salvage (tests, decisions, utilities),
land them as a tiny PR, then delete the branch.
7. Post-merge cleanup: pull main, delete local + remote
branches. Verify squash-merge before -D.
Bail at any step rather than ship a broken branch.
Save as ~/.lingcode/skills/finishing-a-development-branch/SKILL.md — see Install a skill for the exact location and how skills get discovered.