Used before submitting a PR upstream to GitHub, to first converge the approach, commit history, CI, and evidence with low interference within the user's fork, then organize it into a formal upstream PR.
Choose the path first
By default, do an internal draft first, then prepare the formal upstream PR.
- Internal draft: used for exploration and convergence. The PR is opened within the user's fork, with Chinese title and body by default, and low interference by default.
- Formal upstream PR: used for submission to upstream reviewers. The title, body, and commit history are reorganized, retaining only the motivation, behavior changes, and verification evidence needed upstream.
- Formal PR replay: when the formal PR needs its own red/green/cleanup workflow URL, create a new formal branch from the upstream baseline and replay the commits stage by stage on the formal draft PR.
If the user explicitly asks to skip the internal draft, go directly to the formal upstream PR process; if the user asks for it to be "as if the internal PR never existed", rebuild the formal branch from the latest upstream baseline, without reusing the internal draft branch history.
Invariants
- Internal draft is low-interference by default: it does not trigger upstream issue / PR / discussion backlinks, timeline mentions, or notifications.
- The title and body of the internal draft are in Chinese by default; unless the user explicitly requests English, or the target repository/team conventions require English.
- The PR body of the internal draft should retain relevant upstream issue / PR / discussion / commit background links as much as possible; low interference is achieved through
redirect.github.comand avoiding closing keywords, not by omitting key context. - During the internal exploration phase, do not use
fixes/closes/resolvesor other keywords that may automatically close upstream issues. - The formal upstream PR uses a repo-native perspective and does not retain the narrative of "internal draft / fork draft".
- Whether the formal upstream PR uses real issue numbers, plain GitHub links, or closing keywords is decided according to the user's latest instructions and the target repository conventions.
- During the internal draft phase, when the user requests modifications, adjustments, or continued implementation, by default commit and push to the internal PR branch after completing the changes; unless the user explicitly asks to stop locally and wait for review first.
- During the formal upstream PR phase, ordinary modification requests by default only make local changes and explanations, without automatically committing or pushing; unless the user explicitly asks to commit/push, or it has already explicitly entered the red/green/cleanup push steps of the formal PR replay.
- Before committing or pushing, use
git-workflow, and do not bring unrelated local changes into the PR. - When creating or reading GitHub PRs, checks, workflows, or jobs, use
github-cli。
Linking strategy
When clickable links are needed, do not paste long bare URLs; choose the link form according to the PR scenario.
- When referencing upstream issue / PR / commit / discussion in an internal draft or other low-interference scenario, by default use Markdown links together with
redirect.github.com, for example[RedisShake PR 1050](https://redirect.github.com/tair-opensource/RedisShake/pull/1050)。 - If the internal draft originates from a clear upstream issue / PR / discussion, by default add a short "Related information" or "Background" section to the PR body listing these links; do not omit the source context the reviewer needs out of concern about backlinks.
- The formal upstream PR uses repo-native references; same-repository issue / PR by default are written as
#1050In this form, GitHub automatically renders and associates them. Only switch to Markdown URLs when crossing repositories, when custom link text is needed, or when the user explicitly requests low interference. - In formal upstream PRs, if you want same-repository issues / PRs to automatically display their titles, prefer writing bare references as standalone list items, for example
- #1050. In ordinary paragraphs,#1050, #1051usually only displays the number and does not expand the title. Do not use a task list just for title rendering unless checkbox / task tracking semantics are genuinely needed. - Try not to use inline code for upstream URLs; only when in non-Markdown environments such as titles, branch names, or commit messages, or when clickable links are explicitly not wanted, write
owner/repo#123、#123and URLs as plain text or inline code. - Titles, branch names, and commit messages are not reliable Markdown environments; in internal drafts, do not write
#123、owner/repo#123, full GitHub URLs, or closing keywords. - Write evidence links such as workflow runs, jobs, artifacts, and logs as short link text, for example
[失败记录](...)、[通过记录](...)、[CI](...); write the meaning of the evidence in the body text before and after the link. - For same-repository commit evidence, by default write the full 40-character SHA bare, without wrapping it in inline code; GitHub will automatically recognize same-repository commit SHAs as links and display them nicely.
- Only when crossing repositories, when disambiguation is needed, or when the user explicitly requests a clickable commit, write the commit as a Markdown link; for the link text, also prefer using the full 40-character SHA.
- Only fall back to a short SHA when the user explicitly requests it, when interface space is very limited, or when the target context only accepts short references.
Internal Draft Process
- Confirm the baseline.
- Confirm whether the user's fork has a baseline branch aligned with upstream, for example
upstream_main。 - Fetch the upstream target branch and the fork baseline branch, and confirm whether the two are consistent.
- If the fork baseline branch can fast-forward to upstream, update it according to the user's authorization; if it has diverged or has extra commits, stop and confirm.
- Confirm whether the user's fork has a baseline branch aligned with upstream, for example
- Create a development branch.
- Create a feature branch from the fork baseline branch.
- The branch contains only the commits needed for the current task.
- By default, branch names do not include upstream issue / PR numbers.
- Create an internal fork draft PR.
- The PR repo points to the user's fork, and base points to the fork baseline branch.
- Handle the title, body, branch name, and commit message according to the low-interference rules.
- Write the PR body for internal reviewers, explaining the background, related information, changes, verification, risks, and points to be confirmed.
- If there is clear upstream issue / PR / discussion / commit background, list it in the PR body using
redirect.github.comMarkdown links; the title, branch name, and commit message should still avoid directly writing#123、owner/repo#123or full GitHub URLs. - Write the draft body preferentially to
/tmp/*.md, then usegh pr create --body-fileorgh pr edit --body-file。
- Internal convergence.
- Wait for the necessary CI and internal review.
- For subsequent changes to the internal PR, by default push follow-up commits normally to the internal PR branch.
- Record conclusions valuable for the formal upstream PR; do not copy over the exploration process, temporary workflows, and internal discussions as-is.
Formal Upstream PR Process
- Create the formal PR branch from the latest upstream baseline, or organize a branch from the internal draft containing only the final changes.
- Reorganize the title, body, and commit history so that the final diff looks like it was designed this way from the start.
- The PR body should contain only the information an upstream reviewer needs:
- Why this change is needed.
- What user-visible behavior or maintenance boundary was changed.
- How to verify it, and where the evidence entry point is.
- The PR body should be rewritten from the final net change; do not retain internal drafts, temporary experiments, reruns, or traces of designs that were once added and then removed. If necessary, you may temporarily do rendering experiments in the PR description, but the final body should reflect only the final state.
- By default, do not list local formatting, lint, or test commands; if CI covers these, cite the CI evidence directly.
- If the upstream maintainer does not want to keep multiple commits, then squash or reorder the history as requested by the reviewer.
- Subsequent changes to a formal upstream PR should by default stay local first, and be committed and pushed only after user confirmation.
Red / Green evidence
Use three-stage evidence only when a bugfix needs to prove that the regression test is effective. Do not push red and green all at once; otherwise the red evidence becomes weaker.
- Red: Add only the regression test, focused check, or temporary CI needed to reproduce the problem, without the fix code.
- The old implementation must still compile.
- The failure must come from a behavioral assertion, not from a missing symbol in the fix, platform configuration, dependency resolution, generated files, lint, or the temporary workflow itself.
- After pushing, wait for the target workflow/job to clearly fail, and record the commit SHA, workflow/job URL, and failure summary.
- Green: Add only production code or the real implementation.
- Do not modify tests that were already confirmed effective during the red stage.
- After pushing, wait for the same check or an equivalent check to pass, and record the commit SHA and workflow/job URL.
- Cleanup: Remove temporary workflows, debug scripts, one-off configuration, or temporary matrices.
- Keep the formal regression test and the fix code.
- After the cleanup push, you can update the PR description immediately; you do not need to wait first for all normal CI triggered by the cleanup commit to pass.
- If the final CI is still running, briefly state in the PR body that it is running; then continue to monitor it and update according to the results.
Formal PR replay
When the internal draft has already converged, but the formal PR needs its own red/green/cleanup workflow URLs, replay according to this process.
- Create the formal PR branch from the latest upstream baseline.
- Apply only the red commit and push it, then create a draft PR to the upstream target branch.
- Wait for the formal PR's pull_request workflow or an equivalent check accepted by upstream to fail, and record the URL under the formal PR/repo.
- Apply the green commit and push it, wait for the same check or an equivalent check to pass, and record the URL under the formal PR/repo.
- Apply the cleanup commit and push it, then update the formal PR title and body.
- After the PR description, commit history, and necessary CI status all meet the formal submission standard, mark it ready for review.
For a formal upstream PR, by default prioritize the workflow/job URL triggered by that PR itself. Only when the formal PR URL cannot be obtained and the user accepts it may you fall back to the workflow/job URL automatically triggered by a push to the fork branch, and explain the source in the PR body.
How to write PR body evidence
The PR body should first explain the validation methodology, then provide evidence; do not immediately use labels like Red / Green / Cleanup in place of explanation.
For Validation, only include manual validation beyond CI that can increase reviewer confidence. Do not list routine checks such as lint, unit test, build, etc. that GitHub CI already naturally covers.
Recommended format:
提交历史按“测试有效性 -> 实现修复 -> 清理临时 CI”拆成三段,便于确认新增测试不是只覆盖最终状态。
- c6bb4448e6d337f0b1a7c4a3a3a1bb8b6a0d1234:只加入测试;确认测试能在缺少目标行为时失败:[失败记录](https://github.com/owner/repo/actions/runs/123)。
- a1ec55ef8d2a8c66b5d6c3c2f4a7e9b0c1d23456:只加入修复;确认同一检查通过:[通过记录](https://github.com/owner/repo/actions/runs/456)。
- f00ba47c2a6d9f0b7e8c4d3a2b1c0e9f8a765432:删除临时 workflow;最终 CI 见:[CI](https://github.com/owner/repo/actions/runs/789)。
Keep the three pieces of evidence one per line; each line should only retain the commit, action, and evidence entry point, without expanding into full failure details.
Stop and confirm
- The fork base branch and upstream have diverged, or there are unexplained extra commits.
- A force-push is needed or the fork base branch needs to be rewritten.
- The red phase failure is not caused by the target behavior assertion.
- The green phase requires modifying the red test in order to pass.
- The formal PR needs to reference an upstream issue/PR, but it cannot be determined whether the link will create an unwanted backlink.