第 09 章

GitHub CLI

用 gh 命令操作仓库、PR、release——不离开终端搞定一切

能脚本化的,就别手动点网页

网页太慢

你想做个 PR、看个 issue、发个版本,却要打开浏览器、登录、点一堆

切来切去

你在终端写代码,要开 PR 得切到浏览器,找到仓库,点 New pull request,填表单。打断心流,效率低。

批量操作做不了

想给 10 个 issue 加同一个 label,网页上一个一个点。没有「全选」按钮,纯手工累死。

没法自动化

想写个脚本「每天列出未关闭的 PR」,网页做不到。没有命令行接口,就没法编程化。

本章让 GitHub 回到命令行:用官方 gh 工具,在终端里开 PR、查 issue、发 release、跑 Actions。
所有能点网页的操作,gh 几乎都能做,还能脚本化批量处理。

开始之前

适合谁

  • 熟悉命令行,想少切浏览器
  • 有批量操作、自动化 GitHub 的需求
  • 想发 release、触发 Actions 但嫌网页麻烦

你将学会

  • 安装并认证 gh
  • 用 gh 操作 repo、pr、issue
  • 用 gh release 发版本
  • 触发和查看 Actions
  • 写脚本批量处理任务

本章暂不覆盖

  • gh 扩展开发(进阶)
  • API 直接调用(第 11 章)
  • 企业版功能

gh 是什么

GitHub 官方命令行工具——把网页功能搬进终端

能做什么

  • 仓库:clone、create、fork
  • PR:创建、查看、checkout、合并
  • issue:创建、查看、列表
  • release:创建、上传附件
  • Actions:查看、触发 workflow

和 git 的区别

git 管版本控制(commit/push)。
gh 管 GitHub 平台功能(PR/issue/release)。
两者配合使用,不是替代关系。

gh 是开源的,GitHub 官方维护,更新频繁。它本质是对 GitHub API 的封装——第 11 章你会学到那些 API 的真身。

安装 gh

各平台都有现成包

# macOS
$ brew install gh

# Windows (Scoop)
$ scoop install gh
# 或 (Winget)
$ winget install GitHub.cli

# Linux (Ubuntu/Debian)
$ sudo apt install gh

# 验证安装
$ gh --version
gh version 2.45.0 (2024-xx-xx)

Windows 注意

装完可能要重开终端让 PATH 生效。PowerShell 和 Git Bash 都能用。

认证登录

第一次用 gh 要登录,绑定你的 GitHub 账号

$ gh auth login

# 交互式选择:
# ? What account? → GitHub.com
# ? Protocol? → HTTPS(或 SSH)
# ? Authenticate Git? → Yes
# ? How to authenticate? → Login with a web browser

# 显示一个一次性码,浏览器打开授权页粘贴

认证后

凭证安全保存在系统钥匙串。之后所有 gh 命令自动带认证,不用每次登录。

检查状态

$ gh auth status
✔ Logged in to github.com as 你的用户名
gh auth 会顺便配置 git 凭证,所以装好 gh 后,git push 也能复用这套认证,不用再单独配 PAT。一举两得。

仓库操作

gh repo——比网页更快的仓库管理

# 创建新仓库(自动含远程)
$ gh repo create 我的项目 --public --source=. --push

# clone 仓库(不用输完整 URL)
$ gh repo clone 用户名/仓库名

# 在浏览器打开当前仓库主页
$ gh repo view --web

# fork 别人的仓库并 clone
$ gh repo fork 用户名/仓库名 --clone

# 查看仓库信息
$ gh repo view 用户名/仓库名
gh repo create 的妙处:一条命令完成「建远程 + 关联本地 + push」,比第 01 章手动三步快得多。--source=. 把当前目录作为本地仓库。

创建 PR

gh pr create——不离开终端开 PR

# 在 feature 分支上
$ gh pr create

# 交互式填写标题和描述
# ? Title: 添加登录页面
# ? Body: (打开编辑器写描述)

# 一行命令版(CI 友好)
$ gh pr create --title "添加登录页面" --body "Closes #12"

常用选项

  • --base main:指定目标分支
  • --head feature/x:指定源分支
  • --reviewer alice:指派 reviewer
  • --label bug:加 label
  • --draft:开草稿 PR

PR 管理

查看、检出、合并——一条龙

# 列出当前仓库所有 PR
$ gh pr list

# 查看某个 PR 详情
$ gh pr view 15

# 把别人的 PR 拉到本地测试
$ gh pr checkout 15

# 在浏览器打开 PR
$ gh pr view 15 --web

# 合并 PR(squash/merge/rebase)
$ gh pr merge 15 --squash --delete-branch
gh pr checkout N 特别有用:看到同事的 PR 想在本地跑一下,一条命令把那条分支拉下来,自动切过去。比手动 fetch + checkout 省事。

issue 操作

gh issue——不用打开网页也能管 issue

# 创建 issue
$ gh issue create --title "登录按钮失灵" --body "描述..."

# 列出未关闭的 issue
$ gh issue list

# 列出分配给你的
$ gh issue list --assignee @me

# 查看某条 issue(含讨论)
$ gh issue view 12

# 关闭 issue
$ gh issue close 12

# 重新打开
$ gh issue reopen 12

筛选组合

# 你的、未关闭、bug 标签
$ gh issue list --assignee @me \
    --state open --label bug

Release 是什么

给项目的某个时刻打个「正式标签」——通常是发版

release 包含

  • tag:版本号(如 v1.0.0)
  • 标题和说明:这次更新了什么
  • 附件:可下载的产物(安装包、压缩包)

和 tag 的区别

tag 是 Git 概念(指向某 commit 的命名指针)。
release 是 GitHub 概念——基于 tag 的富信息发布物,带说明和附件。

学生项目何时用 release:课程项目交付、参赛作品提交、开源库发版本。不是每个 commit 都要 release,只在里程碑节点发。

发 release

gh release——命令行发版,CI 友好

# 创建 release(自动打 tag)
$ gh release create v1.0.0 \
    --title "v1.0.0 正式版" \
    --notes "首个公开版本"

# 带二进制附件
$ gh release create v1.0.0 \
    ./dist/app.zip ./dist/app.tar.gz \
    --title "v1.0.0" --notes "发布说明"

# 从 CHANGELOG 自动生成 notes
$ gh release create v1.0.0 --generate-notes

其他操作

  • gh release list:列出所有 release
  • gh release view v1.0.0:查看详情
  • gh release download v1.0.0:下载附件
  • gh release delete v1.0.0:删除

自动发布说明

--generate-notes 让 GitHub 自动写更新日志

它做了什么

对比上一个 release,自动生成:

  • 新增的 commit 标题列表
  • 新合并的 PR(含编号和标题)
  • 新增的贡献者
  • 按规范分类(如 Features / Fixes)

前提

commit 消息和 PR 标题遵循规范(如 Conventional Commits),自动分类才准。
哪怕不规范,至少能列出改动列表,比手写省事。

配合 CI 最佳:workflow 里打 tag 触发,用 --generate-notes 自动发 release,全程无人值守。这是「打 tag 即发版」的常见做法。

提交规范

Conventional Commits——让 commit 消息能被机器读懂

格式:类型(范围): 描述

feat(auth): 添加邮箱登录
fix(api): 修复登录接口空指针
docs: 更新 README 安装步骤
chore: 升级依赖版本
refactor(parser): 抽取公共解析逻辑
类型含义release 分类
feat 新功能 Features
fix bug 修复 Bug Fixes
docs 文档 (一般不进 release notes)
chore 杂项/依赖 (一般不进 release notes)
为什么要遵循:上一张的 --generate-notes 会按 feat / fix 自动归类成 Features / Fixes 章节。commit 写得规范,发版说明就是一键生成的高质量文档;写得随意,只能拿到一串看不懂的标题。

操作 Actions

gh run——查看和触发 workflow

# 列出最近的 workflow 运行
$ gh run list

# 查看某次运行的详情
$ gh run view 12345678

# 查看失败的日志
$ gh run view 12345678 --log-failed

# 手动触发 workflow_dispatch 类型的 workflow
$ gh workflow run deploy.yml

# 重新运行失败的
$ gh run rerun 12345678

# 取消正在运行的
$ gh run cancel 12345678
查失败日志不用开浏览器了:gh run view --log-failed 直接把错误打在终端,配合 grep 快速定位问题。

脚本化实战

批量给 issue 加 label——一行命令搞定

# 把所有未关闭、未分类的 issue 加上 triage 标签
$ gh issue list --state open --json number --jq '.[].number' | \
    while read issue; do
        gh issue edit $issue --add-label triage
    done

拆解

  • --json number:输出 JSON,只取 number 字段
  • --jq '.[].number':用 jq 提取成纯数字列表
  • while read:逐行处理
  • gh issue edit --add-label:给单条加 label

这个模式(list → 提取 → 循环 edit)适用于所有批量场景。

JSON 输出

几乎每个 gh 命令都支持 --json,便于程序化处理

# 列出 PR 的编号和标题
$ gh pr list --json number,title
[
  { "number": 15, "title": "添加登录" },
  { "number": 14, "title": "修复 typo" }
]

# 用 jq 提取纯标题
$ gh pr list --json title --jq '.[].title'
添加登录
修复 typo
--json 和 --jq 是脚本化的核心。--json 指定字段,--jq 用 jq 语法过滤。
不加 --jq 输出完整 JSON,加了的输出处理后结果。这是 gh 设计最妙的地方。

自定义别名

给常用命令起短名,少敲键盘

# 创建别名
$ gh alias set co 'pr checkout'
# 现在 gh co 15 等于 gh pr checkout 15

$ gh alias set mine 'pr list --assignee @me'
# gh mine 列出分配给你的 PR

# 列出所有别名
$ gh alias list

# 删除别名
$ gh alias delete co

什么时候用

有又长又常用的命令时。比如每天要看的「我的 PR」、「带某标签的 issue」。
别名存在配置里,跨机器用 gh sync 同步。

扩展机制

gh extension——装别人写的命令,扩展 gh 能力

# 安装扩展(用户名/仓库名)
$ gh extension install dlvhdr/gh-dash

# 用扩展
$ gh dash
# (打开一个 PR/issue 仪表盘)

# 列出已装扩展
$ gh extension list

# 升级
$ gh extension upgrade --all

生态

GitHub 社区贡献了大量扩展:

  • 仪表盘(gh-dash)
  • 预览 markdown
  • 统计贡献图
  • 批量操作工具

搜索:github 话题 gh-extension

gh 在 CI 里

workflow 中用 gh——自动发 release、评论 PR

steps:
  - uses: actions/checkout@v7
  - run: npm run build

  - name: 发 release
    env:
      GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    run: |
      gh release create v${{ github.run_number }} \
        ./dist/app.zip \
        --generate-notes
workflow 里 gh 自带认证:GITHUB_TOKEN 是 Actions 自动提供的临时令牌,不用手动配 secret。在 step 里设为 GH_TOKEN 环境变量,gh 就能用了。
常见用法:build 后自动发 release、PR 被打开时自动评论、定时检查并关闭陈旧 issue。

日常速查

最常用的 gh 命令组合

场景命令
建项目并推送 gh repo create 名 --public --source=. --push
开 PR gh pr create --fill
看我的任务 gh pr list --assignee @me
发版本 gh release create v1.0 --generate-notes
查 CI 失败 gh run view --log-failed

--fill 自动用 commit 消息填充 PR 标题和描述,超省事。

排错:认证失效

gh 命令报 authentication failed

常见原因

  • token 过期(gh 登录的凭证有期限)
  • 换了电脑没重新登录
  • 改了 GitHub 密码后失效
  • 权限不足(操作私有仓库但 token 没 repo 权限)

修复

重新登录:

$ gh auth login

走完浏览器授权流程即可。
如果只是刷新权限:gh auth refresh。

动手试一试

用 gh 走一遍完整流程

你的任务

任务:纯用 gh 命令完成建仓库、开 PR、发 release。

要求:

  1. gh auth login 完成认证
  2. gh repo create 建新仓库并推送本地代码
  3. 开 feature 分支改点东西,用 gh pr create 开 PR
  4. 用 gh pr merge --squash 合并
  5. 用 gh release create v0.1 --generate-notes 发个版本
  6. 全程不打开浏览器(除非认证)

提示

  1. 忘了命令随时 gh --help 或 gh pr --help
  2. --web 参数能在浏览器打开对应页面
第 09 章

小结

你已经能在终端里完成几乎所有 GitHub 操作了

本章要点

  • gh 是 GitHub 官方 CLI,管平台功能(PR/issue/release)
  • 认证一次永久可用,还顺带给 git 配凭证
  • repo/pr/issue/release/run 五大子命令覆盖日常
  • --json + --jq 让输出可程序化,支持脚本批处理
  • 在 workflow 里用 GITHUB_TOKEN 自动发版、评论
下一步:第 10 章 安全实践 —— 系统讲 SSH/PAT/2FA、分支保护、secret scanning、Dependabot,给你的项目上保险。