github-release

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GitHub Release Skill

GitHub Release Skill

This skill automates the full release workflow for a single-package GitHub repository, from analysis through changelog authoring and PR creation. It relies exclusively on
gh
(GitHub CLI) and
git
no other tools needed.
Steps 1 - 4 are read-only reconnaissance nothing is written to the repo until Step 5, once the version number is confirmed.
此 Skill 自动化单包 GitHub 仓库的完整发布工作流,涵盖分析、编写 changelog 和创建 PR。它仅依赖
gh
(GitHub CLI)和
git
,不需要其他工具。
步骤 1 - 4 是 只读侦察;在步骤 5 确认版本号之前,不会向仓库写入任何内容。

When to Use This Skill

何时使用此 Skill

Use this skill whenever the user wants to cut a new release, publish a new version, bump a version, create a release branch, generate a changelog, or open a release PR on a GitHub repository. Trigger even if the user says something casual like "let's ship a new version" or "time to release".

每当用户想要发布新版本、发布新版、升级版本号、创建发布分支、生成 changelog,或为 GitHub 仓库创建发布 PR 时,都应使用此 Skill。即使用户只是随口说“让我们发布一个新版本”或“该发版了”,也应触发。

Prerequisites

前置条件

Examples below include both Bash and PowerShell variants; Windows users should prefer the PowerShell blocks.
Before starting, verify the environment:
bash
gh auth status                        # must be authenticated
gh repo view --json nameWithOwner     # must be inside a GitHub repo
git status                            # working tree should be clean
If any check fails, stop and tell the user what to fix before continuing.
Then ask the user one question:
"Which directory contains your library's public-facing source code? (e.g.
src/
,
lib/
,
pkg/
- used to focus the diff on what consumers actually see. Press Enter to scan the whole repo.)"
Store the answer as
PUBLIC_PATH
. If empty,
PUBLIC_PATH
is
.
(repo root). Exclude these paths from all diffs regardless:
tests/
,
test/
,
spec/
,
__tests__/
,
docs/
,
*.lock
,
*-lock.json
,
*.sum
, generated files (files with a "do not edit" header comment), and build artefacts.

以下示例同时包含 Bash 和 PowerShell 两种版本;Windows 用户应优先使用 PowerShell 代码块。
开始前,验证环境:
bash
gh auth status                        # must be authenticated
gh repo view --json nameWithOwner     # must be inside a GitHub repo
git status                            # working tree should be clean
如果任何检查失败,请停止并告知用户需要先修复什么,然后再继续。
然后向用户提出一个问题:
"你的库的面向用户的源代码位于哪个目录? (例如
src/
、
lib/
、
pkg/
——用于将 diff 聚焦于使用者实际可见的内容。按 Enter 扫描整个仓库。)"
将答案保存为
PUBLIC_PATH
。如果答案为空,则
PUBLIC_PATH
为
.
(仓库根目录)。 无论何种情况,都从所有 diff 中排除以下路径:
tests/
、
test/
、
spec/
、
__tests__/
、
docs/
、
*.lock
、
*-lock.json
、
*.sum
、生成文件(文件头注释中含有 "do not edit")以及构建产物。

The 9-Step Release Workflow

9 步发布工作流

Work through every step in order. Show the user what command you're about to run and its output. Pause and ask for confirmation only when explicitly noted.

按顺序完成每个步骤。向用户展示即将运行的命令及其输出。仅在明确标注的位置暂停并请求确认。

Step 1 - Ensure main is up to date

步骤 1 - 确保 main 为最新状态

bash
git checkout main
git pull origin main
Stay on
main
for now. The release branch is created in Step 5, after the version is confirmed.

bash
git checkout main
git pull origin main
暂时保持在
main
。发布分支将在步骤 5 创建,即版本确认之后。

Step 2 - Grab the latest version tag

步骤 2 - 获取最新的版本 tag

Why not
gh release list
?
GitHub Releases are an optional layer on top of Git tags. Many repos tag releases with
git tag
without ever creating a GitHub Release, so
gh release list
can return empty even when version tags exist. Reading tags directly from git is the reliable source of truth.
bash
undefined
为什么不用
gh release list
?
GitHub Releases 是构建在 Git tag 之上的可选层。许多仓库会使用
git tag
标记发布,却从未创建 GitHub Release,因此即使版本 tag 已经存在,
gh release list
也可能返回空结果。直接读取 git 中的 tag 才是可靠的事实来源。
bash
undefined

Fetch all tags from remote to ensure local view is current

Fetch all tags from remote to ensure local view is current

git fetch --tags
git fetch --tags

Find the latest version tag, sorted semantically

Find the latest version tag, sorted semantically

--sort=-version:refname handles 1.10.0 > 1.9.0 correctly (unlike alphabetical)

--sort=-version:refname handles 1.10.0 > 1.9.0 correctly (unlike alphabetical)

PREV_TAG=$(git tag --sort=-version:refname | grep -E '^v?[0-9]+.[0-9]+.[0-9]+' | head -1) echo "Latest tag: $PREV_TAG"

```PowerShell
PREV_TAG=$(git tag --sort=-version:refname | grep -E '^v?[0-9]+.[0-9]+.[0-9]+' | head -1) echo "Latest tag: $PREV_TAG"
```PowerShell

Fetch all tags from remote to ensure local view is current

Fetch all tags from remote to ensure local view is current

git fetch --tags
git fetch --tags

Find the latest version tag, sorted semantically

Find the latest version tag, sorted semantically

--sort=-version:refname handles 1.10.0 > 1.9.0 correctly (unlike alphabetical)

--sort=-version:refname handles 1.10.0 > 1.9.0 correctly (unlike alphabetical)

$prevTag = git tag --sort='-version:refname' |
  Select-String '^[vV]?\d+\.\d+\.\d+' |
Select-Object -First 1 -ExpandProperty Line
if ($prevTag) { $prevSha = git rev-list -n 1 $prevTag } else { $prevSha = git rev-list --max-parents=0 HEAD }
Write-Output "Latest tag: $prevTag"

Then verify the tag exists on the remote (not just locally):

```bash
git ls-remote --tags origin | grep "refs/tags/$PREV_TAG$"
If the remote check returns nothing, warn the user that the tag appears to be local-only and hasn't been pushed - they may want to push it before continuing.
  • PREV_TAG
    is the tag name exactly as found (e.g.
    v1.4.2
    ). Strip any leading
    v
    when doing arithmetic; preserve it when naming things.
  • If no tags exist at all, treat
    PREV_TAG
    as
    (none)
    , set
    PREV_SHA
    to the first commit, and default the new version to
    1.0.0
    (skip Step 4 versioning logic; go straight to Step 5).
  • If the tag does not point to a real commit (orphaned tag), fall back to
    git rev-list --max-parents=0 HEAD
    and warn the user.
bash
PREV_SHA=$(git rev-list -n 1 "$PREV_TAG" 2>/dev/null || git rev-list --max-parents=0 HEAD)

$prevTag = git tag --sort='-version:refname' |
  Select-String '^[vV]?\d+\.\d+\.\d+' |
Select-Object -First 1 -ExpandProperty Line
if ($prevTag) { $prevSha = git rev-list -n 1 $prevTag } else { $prevSha = git rev-list --max-parents=0 HEAD }
Write-Output "Latest tag: $prevTag"

然后验证 tag 存在于远程仓库中,而不仅仅存在于本地:

```bash
git ls-remote --tags origin | grep "refs/tags/$PREV_TAG$"
如果远程检查没有返回任何结果,请警告用户:该 tag 似乎仅存在于本地,尚未推送——用户可能需要先推送它再继续。
  • PREV_TAG
    是找到的 tag 的确切名称(例如
    v1.4.2
    )。进行算术运算时去掉前导
    v
    ;命名时则保留。
  • 如果完全不存在任何 tag,将
    PREV_TAG
    视为
    (none)
    ,把
    PREV_SHA
    设为首个 commit,并将新版本默认设为
    1.0.0
    (跳过步骤 4 的版本逻辑;直接进入步骤 5)。
  • 如果 tag 未指向真实 commit(孤立 tag),回退到
    git rev-list --max-parents=0 HEAD
    并警告用户。
bash
PREV_SHA=$(git rev-list -n 1 "$PREV_TAG" 2>/dev/null || git rev-list --max-parents=0 HEAD)

Step 3 - Analyse what changed since the last release

步骤 3 - 分析上次发布以来发生的变更

This step uses two complementary signals. The code diff is the primary source of truth; commit messages provide supporting context about intent.
此步骤使用两个互补的信号。代码 diff 是主要事实来源;commit message 为变更意图提供辅助上下文。

3a - Code diff (primary signal)

3a - 代码 diff(主要信号)

bash
undefined
bash
undefined

Focused diff on the public source path, excluding noise

Focused diff on the public source path, excluding noise

git diff "$PREV_SHA"..HEAD -- "$PUBLIC_PATH"
':(exclude)tests/' ':(exclude)test/' ':(exclude)spec/'
':(exclude)tests/' ':(exclude)docs/'
':(exclude).lock' ':(exclude)-lock.json' ':(exclude)*.sum'

```PowerShell
git diff "$PREV_SHA"..HEAD -- "$PUBLIC_PATH"
':(exclude)tests/' ':(exclude)test/' ':(exclude)spec/'
':(exclude)tests/' ':(exclude)docs/'
':(exclude).lock' ':(exclude)-lock.json' ':(exclude)*.sum'
```PowerShell

Focused diff on the public source path, excluding noise

Focused diff on the public source path, excluding noise

git diff "$($prevSha)..HEAD" -- $publicPath
  ':(exclude)tests/' ':(exclude)test/' ':(exclude)spec/'
':(exclude)tests/' ':(exclude)docs/' ` ':(exclude).lock' ':(exclude)-lock.json' ':(exclude)*.sum'

Read the full diff output. For each changed file, identify:

1. **Removed symbols** - functions, classes, methods, constants, exported names that
   existed before and are now gone. ? Strong signal for MAJOR.
2. **Changed signatures** - functions that exist in both versions but with different
   parameters, return types, or thrown errors. ? Strong signal for MAJOR.
3. **New exported symbols** - public functions, classes, constants that didn't exist
   before. ? Signal for MINOR.
4. **Internal-only changes** - modifications that don't touch any public interface
   (private helpers, unexported functions, algorithm internals). ? PATCH.
5. **Bug fixes** - corrections to logic that was provably wrong (e.g. off-by-one,
   null check, wrong condition), without changing the public API. ? PATCH.

If the diff is very large (thousands of lines), first run the stat summary to
prioritise which files to read in full:

```bash
git diff "$PREV_SHA"..HEAD --stat -- "$PUBLIC_PATH"
Focus your detailed reading on files with the most changes and files whose names suggest they define public interfaces (e.g.
index.*
,
api.*
,
exports.*
,
public.*
,
mod.*
,
__init__.*
).
git diff "$($prevSha)..HEAD" -- $publicPath
  ':(exclude)tests/' ':(exclude)test/' ':(exclude)spec/'
':(exclude)tests/' ':(exclude)docs/' ` ':(exclude).lock' ':(exclude)-lock.json' ':(exclude)*.sum'

完整阅读 diff 输出。对于每个发生变更的文件,识别:

1. **已移除的符号**——此前存在、现已消失的函数、类、方法、常量或导出名称。→ 强烈表明应升级 MAJOR。
2. **签名变更**——两个版本中都存在、但参数、返回类型或抛出的错误不同的函数。→ 强烈表明应升级 MAJOR。
3. **新增导出符号**——此前不存在的公共函数、类或常量。→ 表明应升级 MINOR。
4. **仅限内部的变更**——未触及任何公共接口的修改(私有辅助函数、未导出函数、算法内部实现)。→ PATCH。
5. **Bug 修复**——对可证明存在错误的逻辑进行修正(例如差一错误、空值检查、错误条件),且未改变公共 API。→ PATCH。

如果 diff 非常大(数千行),先运行统计摘要,以确定优先完整阅读哪些文件:

```bash
git diff "$PREV_SHA"..HEAD --stat -- "$PUBLIC_PATH"
详细阅读应聚焦于变更最多的文件,以及文件名表明其定义公共接口的文件(例如
index.*
、
api.*
、
exports.*
、
public.*
、
mod.*
、
__init__.*
)。

3b - Commit log (secondary signal)

3b - Commit log(辅助信号)

bash
git log "$PREV_SHA"..HEAD --oneline --no-merges
Use this to:
  • Understand the intent behind code changes that aren't self-explanatory from the diff alone (e.g. a one-line security fix labelled as such).
  • Catch changes that may be in paths outside
    PUBLIC_PATH
    but are still user-visible (e.g. a CLI flag change in a
    cmd/
    directory).
  • Fill in context for changelog entries where the code alone doesn't tell the whole story.
See
references/commit-classification.md
for mapping message patterns to change types.
bash
git log "$PREV_SHA"..HEAD --oneline --no-merges
使用它来:
  • 理解仅凭 diff 无法明确说明的代码变更背后的意图(例如一行代码的安全修复虽在 commit message 中有明确标注)。
  • 捕获
    PUBLIC_PATH
    之外路径中可能发生的变更,但这些变更仍对用户可见(例如
    cmd/
    目录中的 CLI flag 变更)。
  • 为代码本身无法完整呈现的 changelog 条目补充上下文。
请参阅
references/commit-classification.md
,了解如何将 message 模式映射到变更类型。

3c - Reconcile the two signals

3c - 协调两个信号

When signals agree ? use that classification with confidence.
When signals conflict ? prefer the code diff. Examples:
  • Commit says
    fix: typo
    but the diff shows a removed public method ? treat as MAJOR.
  • Commit says
    feat: new API
    but the diff only touches private internals ? treat as PATCH.
  • Commit says
    chore: refactor
    but the diff adds new exported symbols ? treat as MINOR.
Document any conflicts you notice - flag them to the user during the changelog review in Step 6.

当两个信号一致时 → 使用该分类并给予高度确信。
当两个信号冲突时 → 优先采用代码 diff。示例:
  • Commit 表示
    fix: typo
    ,但 diff 显示移除了一个公共方法 → 按 MAJOR 处理。
  • Commit 表示
    feat: new API
    ,但 diff 只涉及私有内部实现 → 按 PATCH 处理。
  • Commit 表示
    chore: refactor
    ,但 diff 新增了导出符号 → 按 MINOR 处理。
记录发现的任何冲突——在步骤 6 的 changelog 审查期间向用户标记。

Step 4 - Determine the next SemVer version

步骤 4 - 确定下一个 SemVer 版本

Apply these rules to your analysis from Step 3 (full rules in
references/semver-rules.md
):
ConditionBump
Any breaking change to public API (removal, signature change, behaviour change)MAJOR
New exported symbol or feature, no breaking changesMINOR
Bug fix, perf improvement, security fix, docs, chore onlyPATCH
When a release contains a mix, the highest precedence wins:
MAJOR > MINOR > PATCH
.
Compute
NEXT_VERSION
:
  • Split
    PREV_TAG
    into
    MAJOR.MINOR.PATCH
    integers.
  • Apply the appropriate bump.
  • Format as
    vMAJOR.MINOR.PATCH
    .
Present the proposed version to the user with a brief rationale that cites specific code findings, not just commit messages. Example:
"I'm proposing v2.1.0. The diff shows two new exported functions (
NewClient
and
WithTimeout
) in
src/client.go
, and no existing public symbols were removed or changed. Commit messages corroborate this as feature additions."
Ask: "Does this version look right, or would you like to adjust it?" Wait for confirmation before proceeding.

根据步骤 3 的分析应用以下规则(完整规则见
references/semver-rules.md
):
条件升级类型
公共 API 的任何破坏性变更(移除、签名变更、行为变更)MAJOR
新增导出符号或功能,且没有破坏性变更MINOR
Bug 修复、性能改进、安全修复、文档、杂务PATCH
当一次发布包含多种类型时,优先级最高的类型胜出:
MAJOR > MINOR > PATCH
。
计算
NEXT_VERSION
:
  • 将
    PREV_TAG
    拆分为整数形式的
    MAJOR.MINOR.PATCH
    。
  • 应用相应的版本升级。
  • 格式化为
    vMAJOR.MINOR.PATCH
    。
向用户提出建议版本,并给出简短理由,引用具体的代码发现,而不只引用 commit message。示例:
"我建议使用 v2.1.0。diff 显示
src/client.go
中新增了两个导出函数(
NewClient
和
WithTimeout
),且没有现有公共符号被移除或修改。Commit message 也印证了这是功能新增。"
询问:"这个版本合适吗?或者你希望进行调整?" 继续之前等待确认。

Step 5 - Create the release branch

步骤 5 - 创建发布分支

Now that the version is confirmed, create the branch with the correct name from the start:
bash
git checkout -b release/vX.Y.Z
git push -u origin release/vX.Y.Z

现在版本已经确认,从一开始就使用正确的名称创建分支:
bash
git checkout -b release/vX.Y.Z
git push -u origin release/vX.Y.Z

Step 6 - Update CHANGELOG.md

步骤 6 - 更新 CHANGELOG.md

Read the existing
CHANGELOG.md
(or create it if absent). Follow the Keep a Changelog format strictly.
Structure to insert at the top (just below the
# Changelog
header):
markdown
undefined
读取现有的
CHANGELOG.md
(如果不存在则创建)。严格遵循 Keep a Changelog 格式。
要在顶部插入的结构(紧接在
# Changelog
标题下方):
markdown
undefined

[X.Y.Z] - YYYY-MM-DD

[X.Y.Z] - YYYY-MM-DD

Added

Added

  • ...
  • ...

Changed

Changed

  • ...
  • ...

Deprecated

Deprecated

  • ...
  • ...

Removed

Removed

  • ...
  • ...

Fixed

Fixed

  • ...
  • ...

Security

Security

  • ...

Rules:
- Use today's date in `YYYY-MM-DD` format.
- Omit sections that have no entries - don't leave empty headings.
- Write entries in **plain English from a user's perspective**, derived primarily
  from what the code diff shows, supplemented by commit message context.
  Good: *"Added `WithTimeout` option to HTTP client constructor."*
  Bad: *"feat: add timeout cfg param"*
- Map findings to sections:
  - New exported symbol ? Added
  - Breaking removal ? Removed
  - Breaking change to existing API ? Changed (flag it as breaking)
  - Bug/logic fix, perf ? Fixed
  - Security fix ? Security
  - Internal refactor, docs, chore, test ? omit unless user-visible
- If a commit message revealed intent that the code diff alone wouldn't convey
  (e.g. a security fix disguised as a one-line change), include that context in
  the changelog entry.
- Also update the diff link at the bottom of the file:
  ```markdown
  [X.Y.Z]: https://github.com/OWNER/REPO/compare/vPREV...vNEXT
Show the user the proposed changelog section before writing it to disk. If any signal conflicts were found in Step 3c, flag them here so the user can verify. Ask: "Does this changelog look accurate? Any entries to add, remove, or reword?" Incorporate feedback, then write to disk.

  • ...

规则:
- 使用今天的日期,格式为 `YYYY-MM-DD`。
- 省略没有任何条目的分区——不要留下空标题。
- 主要依据代码 diff 显示的内容,并辅以 commit message 上下文,以**面向用户的通俗英文**编写条目。
  正确:*"Added `WithTimeout` option to HTTP client constructor."*
  错误:*"feat: add timeout cfg param"*
- 将发现映射到各分区:
  - 新增导出符号 → Added
  - 破坏性移除 → Removed
  - 对现有 API 的破坏性变更 → Changed(并标记为 breaking)
  - Bug 或逻辑修复、性能改进 → Fixed
  - 安全修复 → Security
  - 内部重构、文档、杂务、测试 → 除非对用户可见,否则省略
- 如果 commit message 揭示了仅靠代码 diff 无法传达的意图(例如伪装成一行代码修改的安全修复),请在 changelog 条目中包含这些上下文。
- 还要更新文件底部的 diff link:
  ```markdown
  [X.Y.Z]: https://github.com/OWNER/REPO/compare/vPREV...vNEXT
在写入磁盘前,向用户展示建议的 changelog 段落。 如果步骤 3c 中发现任何信号冲突,请在此标记,以便用户验证。 询问:"这个 changelog 准确吗?需要添加、删除或改写任何条目吗?" 纳入反馈后,再写入磁盘。

Step 7 - Commit and push

步骤 7 - 提交并推送

bash
git add CHANGELOG.md
git commit -m "chore: release vX.Y.Z"
git push origin release/vX.Y.Z
Confirm the push succeeded before moving on.

bash
git add CHANGELOG.md
git commit -m "chore: release vX.Y.Z"
git push origin release/vX.Y.Z
确认推送成功后继续。

Step 8 - Open a Pull Request

步骤 8 - 创建 Pull Request

?? IMPORTANT: Always use
--body-file
to pass PR body text, never
--body
with inline text. Inline escape sequences like
\n
are not interpreted as newlines by PowerShell and will appear as literal text in the PR. Using a file ensures proper markdown formatting.
bash
gh pr create \
  --base main \
  --head release/vX.Y.Z \
  --title "Release vX.Y.Z" \
  --body "$(cat <<'EOF'
⚠️ 重要: 始终使用
--body-file
传递 PR 正文,绝不要使用带内联文本的
--body
。 PowerShell 不会将内联转义序列(例如
\n
)解释为换行,而会将其显示为字面文本。使用文件可确保 Markdown 格式正确。
bash
gh pr create \
  --base main \
  --head release/vX.Y.Z \
  --title "Release vX.Y.Z" \
  --body "$(cat <<'EOF'

Release vX.Y.Z

Release vX.Y.Z

This PR prepares the vX.Y.Z release.
This PR prepares the vX.Y.Z release.

What's included

What's included

<!-- paste the changelog section here -->
<!-- paste the changelog section here -->

Checklist

Checklist

  • Changelog reviewed
  • Version bump verified
  • CI passing
After merging, create the tag on the merge commit: ``` git tag vX.Y.Z <merge-commit-sha> git push origin vX.Y.Z ``` EOF )"

````PowerShell
  • Changelog reviewed
  • Version bump verified
  • CI passing
After merging, create the tag on the merge commit: ``` git tag vX.Y.Z <merge-commit-sha> git push origin vX.Y.Z ``` EOF )"

````PowerShell

Create PR body using here-string (preserves actual newlines, not escape sequences)

Create PR body using here-string (preserves actual newlines, not escape sequences)

$prBody = @"
$prBody = @"

Release vX.Y.Z

Release vX.Y.Z

This PR prepares the vX.Y.Z release.
This PR prepares the vX.Y.Z release.

What's included

What's included

<paste changelog here>
<paste changelog here>

Checklist

Checklist

  • Changelog reviewed
  • Version bump verified
  • CI passing
After merging, create the tag on the merge commit:
git tag vX.Y.Z <merge-commit-sha>
git push origin vX.Y.Z
"@
  • Changelog reviewed
  • Version bump verified
  • CI passing
After merging, create the tag on the merge commit:
git tag vX.Y.Z <merge-commit-sha>
git push origin vX.Y.Z
"@

Write to file and use --body-file (do NOT use inline --body with escape sequences)

Write to file and use --body-file (do NOT use inline --body with escape sequences)

$prBody | Out-File -FilePath release_pr_body.md -Encoding utf8 -NoNewline gh pr create --base main --head release/vX.Y.Z --title "Release vX.Y.Z" --body-file release_pr_body.md

Paste the changelog section into the PR body's "What's included" block (or leave placeholder for manual review).


---
$prBody | Out-File -FilePath release_pr_body.md -Encoding utf8 -NoNewline gh pr create --base main --head release/vX.Y.Z --title "Release vX.Y.Z" --body-file release_pr_body.md

将 changelog 段落粘贴到 PR 正文的 "What's included" 区块中,或者保留占位符供人工审查。

---

Step 9 - Hand off to the user

步骤 9 - 移交给用户

Tell the user:
Release PR is open! ??
New version: vX.Y.Z
Once the PR is reviewed and merged, you'll need to create the tag yourself on the merge commit:
bash
git tag vX.Y.Z <merge-commit-sha>
git push origin vX.Y.Z
Then go to GitHub Releases and publish the release from that tag. You can copy the changelog section directly into the release notes.

告知用户:
发布 PR 已创建!🎉
新版本:vX.Y.Z
PR 审核并合并后,你需要在 merge commit 上自行创建 tag:
bash
git tag vX.Y.Z <merge-commit-sha>
git push origin vX.Y.Z
然后前往 GitHub Releases,并从该 tag 发布版本。你可以直接将 changelog 段落复制到 release notes 中。

Error handling

错误处理

SituationWhat to do
gh auth status
fails
Stop; tell user to run
gh auth login
Not inside a git repoStop; tell user to
cd
into their repo
Working tree is dirtyWarn; ask if they want to stash or abort
No commits since last tagTell user there's nothing to release
Tag exists but points to no commitUse first commit as diff base; warn user
Latest tag exists locally but not on remoteWarn user; ask if they want to push the tag first or continue anyway
Diff is empty for
PUBLIC_PATH
but commits exist
Warn; all changes may be internal; ask if they still want to proceed
git push
fails (e.g. protected branch rules)
Report the error verbatim; suggest they check branch protection settings

情况处理方式
gh auth status
失败
停止;告知用户运行
gh auth login
当前不在 git 仓库中停止;告知用户使用
cd
进入仓库
工作区不干净警告;询问用户是希望 stash 还是中止
自上次 tag 后没有 commit告知用户没有可发布的内容
tag 存在但未指向任何 commit使用首个 commit 作为 diff 基准;警告用户
最新 tag 仅存在于本地,远程不存在警告用户;询问是希望先推送 tag,还是无论如何继续
PUBLIC_PATH
的 diff 为空,但存在 commit
警告;所有变更可能都属于内部修改;询问用户是否仍要继续
git push
失败(例如受保护分支规则)
原样报告错误;建议用户检查分支保护设置

Troubleshooting in PowerShell

PowerShell 故障排除

  • If a command that works locally prints gh usage or treats a subcommand as separate token, ensure you're invoking the gh.exe on PATH (Get-Command gh) and avoid passing unexpanded nested substitutions; use the PowerShell patterns above.
  • Recommend tests: gh --version; git fetch --tags; run the PowerShell snippet to set $prevTag and run git diff --name-only $prevSha..HEAD -- src/

  • 如果某个在本地可正常运行的命令打印了 gh usage,或将子命令视为单独的 token,请确保调用的是 PATH 中的 gh.exe(Get-Command gh),并避免传递未展开的嵌套替换;请使用上述 PowerShell 模式。
  • 建议测试:gh --version;git fetch --tags;运行 PowerShell 代码片段设置 $prevTag,并执行 git diff --name-only $prevSha..HEAD -- src/

Limitations

限制

  • Requires the
    gh
    CLI to be installed and authenticated.
  • Requires git tags to determine current version.

  • 要求已安装
    gh
    CLI 并完成认证。
  • 要求使用 git tag 确定当前版本。

Reference files

参考文件

  • references/semver-rules.md
    - Extended SemVer decision rules and edge cases
  • references/commit-classification.md
    - Heuristics for classifying commit messages into change types
  • references/semver-rules.md
    - 扩展的 SemVer 决策规则和边缘情况
  • references/commit-classification.md
    - 将 commit message 分类为变更类型的启发式规则