"所有测试通过"并不等于完成。只有当差异正是你所期望的、main 分支没有在你之下漂移、且集成路径符合项目约定时,分支才能干净落地。LingCode 执行收尾清单 — 并在正确答案是"丢掉它"时告诉你。
最简单的收尾流程是:本地测试通过,推送,开 PR,完事。但从测试绿到干净合并,有四件事经常出错:
本教程中的技能为 LingCode 提供了明确的收尾协议:审查差异、与 main 同步、选择集成路径,以及在工作不值得发布时干净放弃。
git log main 推断。在做任何其他事情之前,让 LingCode 将分支中的实际内容与分支本应完成的任务进行比对:
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.
意外改动是最容易避免的审查意见。顺手修复的内容则需要判断 — 小的可以随行,真正的重构应该单独开 PR,让下一个看 git log 的人明白为什么。
本地绿不等于集成后绿。让 LingCode 按仓库惯例将 main 并入分支,然后重新跑完整测试套件:
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.
这是让"我完成了"的声明变得可验证的环节。让 LingCode 执行固定清单,并对每一项报告 PASS/FAIL:
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.
"遇到第一个 FAIL 就停下"是铁律。忍不住带着警告合并的冲动,正是问题分支落地的方式。
从一个完成的分支出发,有三条合理的路径。请有意识地选择:
gh pr create。让 LingCode 根据仓库历史推荐一条路径:
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.
如果选择 PR 路径,描述应该反映补丁实际做了什么 — 而不是你在分支开始时的计划。让 LingCode 从最终差异起草,而不是从原始任务描述:
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.
"Why" 一节是大家最容易跳过、而审阅者最需要的部分。为什么现在做,为什么用这种方案,为什么不用显而易见的替代方案。
有时正确的答案就是丢掉这个分支。该技能让 LingCode 识别这些信号,并主动提出,而不是硬推:
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.
带着干净的 salvage PR 丢弃一个分支不是失败 — 这是在不继承其错误的情况下,保留分支所学成果的最低成本方式。
分支删除之前,收尾清单都不算完成。让 LingCode 来清理:
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.
过时的分支,是六个月后"那个实验去哪儿了"这类排查的起点。
收尾协议被打包成一个技能 — 将它放入你的技能文件夹,在测试通过后让 LingCode "完成这个分支":
---
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.
保存为 ~/.lingcode/skills/finishing-a-development-branch/SKILL.md — 查看安装技能了解确切位置及技能的发现机制。