第二十章. 命令行重度依赖:GitHub CLI (gh) 完整的使用教程,涵盖全方位细节讲解!

第二十章. 命令行重度依赖:GitHub CLI (gh) 完整的使用教程,涵盖全方位细节讲解!

在前面的章节中,我们已经熟练掌握了 git 命令来管理本地代码版本和远程同步。然而,必须厘清一个核心概念:git 的边界止步于“代码仓库(Repository)”本身

一旦涉及到 GitHub 平台特有的协作功能——如 Pull Requests (PR)、Issues(工单)、Releases(版本发布)、Actions(CI/CD 日志)、Fork 同步等——大多数开发者的第一反应仍然是打开浏览器,输入网址,通过鼠标点击来完成操作。

这种“终端写代码 -> 浏览器提 PR -> 终端切分支 -> 浏览器看 Review”的频繁上下文切换(Context Switching),是开发效率的隐形杀手。

20.1. gh 概览与环境准备

GitHub CLI(命令行工具,命令为 gh)的出现,旨在弥合这一断层。

20.1.1. 它是 git 的上层封装

gh 不是 git 的替代品,而是它的 上层扩展。如果说 git 负责管理 文件内容(Commit, Push, Pull),那么 gh 则负责管理 协作流程

它将 GitHub 的网页功能搬进了终端,支持以下核心 Scope(作用域):

  • Pull Requests: 创建、审查、合并、checkout 他人的 PR 分支。
  • Issues: 快速浏览、创建、分配工单。
  • Actions: 触发 Workflow,甚至直接在终端查看构建失败的日志。
  • Extensions: 极其强大的扩展系统,允许社区编写插件来增强功能。

对于追求极致效率的工程师,gh 能够将复杂的 UI 点击操作转化为可复用、可自动化的脚本指令。

20.1.2. 跨平台安装指南

在配置之前,请根据你的操作系统安装 gh

注意:安装完成后,请在终端执行 gh --version 验证是否安装成功。

macOS (推荐 Homebrew)

这是最省心的安装方式,同时也会自动管理更新。

1
brew install gh

Windows

推荐使用 winget (Windows Package Manager) 或 scoop

1
2
3
4
5
6
# 使用 Winget (推荐)
winget install GitHub.cli

# 或者使用 Scoop
scoop bucket add main
scoop install gh

Linux

以 Ubuntu/Debian 为例(其他发行版请参考官方文档):

1
2
3
4
5
6
7
# 1. 下载密钥环
type -p curl >/dev/null || sudo apt install curl -y
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg \
&& chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& sudo apt update \
&& sudo apt install gh -y

20.2. 搭建无浏览器工作流:认证与配置

工具安装完毕后,必须建立本地终端与 GitHub 平台的安全连接。与 git 仅需 SSH Key 不同,gh 代表你操作 GitHub API,因此需要更高层级的授权。

20.2.1. 认证机制详解:Web 登录 vs Token 登录

gh 提供了多种登录方式,分别适用于“人类用户”和“机器用户(CI/CD)”。

交互式 Web 登录(适用于本地开发)

这是最常用的方式。执行以下命令:

1
gh auth login

终端会启动一个交互式向导。请按照以下步骤操作:

  1. Select account type: 选择 GitHub.com
  2. What is your preferred protocol for Git operations?: 强烈建议选择 SSH。这会自动复用你本地已配置的 SSH Key,或者引导你生成新的并自动上传到 GitHub。如果选择 HTTPS,后续每次操作可能需要输入 Token,且不够安全。
  3. Authenticate Git with your GitHub credentials?: 选择 Yes
  4. How would you like to authenticate GitHub CLI?: 选择 Login with a web browser

系统会生成一个一次性验证码(One-time code),按 Enter 键后会自动打开浏览器,粘贴验证码并授权。

底层原理:此过程使用的是 OAuth 2.0 设备授权流(Device Authorization Flow)。授权成功后,gh 会在 ~/.config/gh/hosts.yml 中存储一个 oauth_token。这个 Token 拥有读写仓库、用户信息等权限。

Token 登录(适用于脚本或受限环境)

在远程服务器或 CI/CD 容器中,无法打开浏览器,此时需要使用 Personal Access Token (PAT)。

  1. 在 GitHub 网页生成 PAT (Settings -> Developer settings -> Personal access tokens)。
  2. 确保勾选权限:repo, read:org, workflow
  3. 在终端执行:
1
2
3
4
5
6
# 方法一:通过标准输入管道
echo "YOUR_TOKEN_HERE" | gh auth login --with-token

# 方法二:通过环境变量(推荐用于 CI)
export GH_TOKEN="YOUR_TOKEN_HERE"
# 此时直接运行 gh 命令即可,无需显式 login

20.2.2. 协议偏好与编辑器配置

为了实现全键盘操作,必须配置默认的协议和文本编辑器。

绑定编辑器

当你执行 gh pr create 但不使用 -b 参数指定正文时,gh 会尝试打开一个编辑器让你编写 Markdown。默认可能是 nanovi。建议将其绑定为你最熟悉的编辑器,如 VS Code。

1
2
# 将编辑器设置为 VS Code (需要 code 命令在 PATH 中)
gh config set editor "code --wait"

参数解析
--wait 至关重要。它告诉终端“等待 VS Code 关闭该文件后再继续执行后续命令”。如果不加这个参数,VS Code 会在后台打开,而终端会认为你输入了空内容并立即结束命令,导致 PR 创建失败。

20.2.3. 常用配置清单

以下是 gh config 的常用配置项,建议在初始化环境时一次性检查。

配置项命令作用推荐值
git_protocolgh config set git_protocol sshGit 操作使用的协议ssh
editorgh config set editor "code --wait"交互式输入调用的编辑器code --waitvim
promptgh config set prompt enabled启用交互式提示enabled
pagergh config set pager less长文本分页查看器lesscat (如果不想要分页)
browsergh config set browser chromegh browse 打开的浏览器系统默认即可

安装和配置完成后,你可以尝试运行以下命令来验证你的环境是否已经准备好处理实际工作流:
gh repo view --web (这应该会直接在浏览器中打开当前目录对应的 GitHub 仓库页面)。


20.3. PR 的全生命周期命令行管理

Pull Request (PR) 的本质是将 一个分支的修改 合并到 另一个分支。在浏览器中,你需要先手动 git push,打开网页,点击 “Compare & pull request”。gh 的强大之处在于,它能在一个命令里自动完成“创建远程分支 -> 推送代码 -> 生成 PR”的全过程。

20.3.1 提交你的第一个命令行版 pr

关键前置:基于分支的工作流

在执行 gh pr create 之前,请务必遵守以下“黄金法则”:不要在 main 分支直接操作,始终新建一个功能分支;新建分支前,确保你的 main 是最新的。请在终端执行以下标准起手式:

1
2
3
4
5
6
7
8
9
10
# 1. 切换回主分支并拉取最新代码(解决 ! [rejected] 错误的关键)
git checkout main && git pull origin main

# 2. 基于最新的 main 新建一个分支(比如叫 feature/demo-pr)
git checkout -b feature/demo-pr

# 3. 随便修改一个文件,并提交(gh 需要有新的 Commit 才能提 PR)
echo "test content" >> test.txt
git add .
git commit -m "feat: add test content"

注意:此时你 不需要 手动执行 git pushgh 会帮我们做这一步。

交互式创建实战详解

现在处于 feature/demo-pr 分支且有新 Commit 后,执行 gh pr create 进入交互模式:

  1. 选择目标仓库:如果是 Fork 的项目,通常选择 Upstream(上游仓库)。
  2. 填写标题 (Title):输入 PR 标题。如果你刚才的 Commit 信息写得规范,这里直接按 Enter 即可自动填充。
  3. 填写正文 (Body):推荐选择 Launch editor,它会调用 VS Code 让我在临时文件中编写详细的 Markdown 描述。
  4. 后续操作 (What’s next?):这是最关键的一步。建议选择 Add metadata 进入元数据编辑模式:
    • Reviewers:输入名字指派审查人,一般他会询问你是谁
    • Assignees:默认会是自己
    • Projects:如果你看到 warning: no projects to choose from请直接忽略。这仅代表你没有在网页端创建项目看板,并不影响 PR 的提交与合并。
  5. 最终提交:填完信息后选择 Submit。此时 gh 会自动执行 git push 并调用 API 创建 PR。

常见故障:Workflow 权限陷阱与恢复

如果您跟随本书前几章的实战,修改了 .github/workflows/ 目录下的 CI 配置文件(例如 auto-release.yml),在执行 Submit 时,极大概率会遇到如下报错:

1
! [remote rejected] HEAD -> feature/demo-pr (refusing to allow an OAuth App to create or update workflow `.github/workflows/auto-release.yml` without `workflow` scope)

这是 GitHub 的安全机制。普通代码仅需 repo 权限,而 Workflow 文件因涉及 CI/CD 流程控制,必须拥有特殊的 workflow 权限。你手中的 gh 工具默认可能未申请此权限。

解决方案与现场恢复

  1. 升级权限:在终端执行 gh auth refresh -s workflow。系统会要求你再次打开浏览器授权,请务必在授权页确认包含了 “Update GitHub Action workflows”。
  2. 恢复现场(后悔药):权限升级后,不需要重写 PR 文案!直接复制报错信息中提示的 recover 命令(如下所示),这会自动恢复刚才填写的标题和正文并重新提交:
1
2
# 注意:后面的 json 路径是动态生成的,请复制你自己终端报错信息里的那个路径
gh pr create --recover C:\Users\Prorise\AppData\Local\Temp\gh1680964837.json

我们成功的发起了一次命令行版本的 PR 流程!

image-20251201200644029

您的批评非常到位。**“先查后办”**是命令行操作的基本逻辑,跳过检索直接讲操作 ID,确实不仅反人类,而且在实际工作中完全行不通(毕竟谁能背下 PR 编号呢?)。


20.3.2. 检索与定位 PR

在对 PR 进行任何操作之前,我们首先需要知道当前仓库里发生了什么。在网页端,这需要点击 “Pull Requests” 标签页;在终端,我们通过 list 命令建立全局视野。

基础列表与状态筛选

默认情况下,gh 只显示当前仓库中 Open 状态的 PR。

1
2
# 查看当前所有待处理的 PR
gh pr list

输出结果清晰明了,包含编号(ID)、标题、分支名和创建状态:

1
2
ID  TITLE                       BRANCH                                                      CREATED AT
#9 chore(main): release 1.7.0 release-please--branches--main--components--vite-cicd-demo about 26 minutes ago

如果你想查看历史记录,或者查找已经被合并/关闭的 PR,可以使用 --state 参数:

1
2
3
4
5
# 查看所有 PR(包括 Closed 和 Merged)
gh pr list --state all

# 仅查看已合并的 PR
gh pr list --state merged

精准过滤:找到属于你的任务

在大型项目中,PR 列表可能成百上千。gh 提供了强大的过滤器,让你只关注与自己相关的代码。

1
2
3
4
5
6
7
8
# 查看所有指派给我的 PR(作为 Assignee)
gh pr list --assignee "@me"

# 查看需要我进行 Code Review 的 PR
gh pr list --search "review-requested:@me is:open"

# 查看特定标签的 PR(如 bug 修复)
gh pr list --label "bug"

查看详情与浏览器联动

当你通过列表找到了感兴趣的 ID(例如 #123),如果不确定是否需要拉取到本地,可以先快速预览元数据:

1
gh pr view 123

这会显示 PR 的完整描述、CI 状态 checks 和最新的 Commit 列表。如果你觉得终端看大段文字太累,也可以直接按 Ctrl+Click 点击终端里的链接,或者使用 --web 参数在浏览器中打开特定 PR:gh pr view 123 --web

20.3.3. 本地审查:Checkout 与 Diff

当我们确定要审查某个 PR(假设 ID 为 123)时,gh 提供了最具杀伤力的功能:一键本地化环境切换

本地化的 checkout 革命

传统痛点在于:同事提了一个 PR,你想拉下来跑代码。你需要 git fetch,找到那串冗长的分支名,建立追踪关系,测完还得删。现在,你只需要一个 ID:

1
gh pr checkout 123

底层行为解析
gh 会自动执行一连串 Git 复杂操作:识别 PR 源分支(即使来自 Fork 仓库)、添加 Remote、拉取代码、创建本地分支并建立 Upstream 追踪。
实战场景:当你正在 review 代码,发现一个疑似 bug。执行 gh pr checkout 123 -> 本地运行 npm test -> 复现 Bug -> 修改代码 -> git push。如果你有写权限,你的 push 会直接更新该 PR。

差异对比 (Diff)

虽然大多数 Review 是在网页上进行的,但在终端结合工具查看 Diff 效率极高。

1
gh pr diff 123

配置建议:配合第 14 章介绍的 delta 工具,体验极佳。请确保配置:gh config set pager "delta"

20.3.4. 决策闭环:批复与合并

在本地验证无误后,我们无需切回浏览器,直接在终端完成 PR 生命周期的最后一步。

提交评审意见

1
2
3
4
5
6
7
8
# 同意合并 (Approve)
gh pr review 123 --approve --body "LGTM. Verified locally."

# 提出修改意见 (Request Changes)
gh pr review 123 --request-changes --body "Tests failed on my local env. Please fix."

# 仅留言 (Comment)
gh pr review 123 --comment --body "Good job, but consider optimizing line 45."

20.3.4. 合并与清理

当 CI 通过且 Review 通过后,执行合并。

1
gh pr merge 123 --squash --delete-branch

参数详解

参数说明
--squash压缩合并。将 PR 的所有 commit 压缩为一个,保持主分支历史整洁。推荐作为默认策略。
--merge普通合并(Merge Commit)。保留完整历史。
--rebase变基合并。
--delete-branch重要。合并成功后,自动删除远程和本地的 Feature 分支。防止僵尸分支堆积。
--auto自动合并。如果 CI 正在跑,该命令会挂起,等待 CI 全绿后自动触发合并。

这是为你更新和拓展后的笔记内容。我已将 gh dash 部分进行了大幅扩充,加入了文件 Diff 查看、Delta 集成配置以及自定义按键映射等高阶用法,同时保持了扁平化的结构和原本的文风,去除了嵌套列表和比喻修辞。


20.4. 扩展生态:打造终端定制化工作台

如果说 gh 的核心命令提供了 Git 的上层封装,那么 Extensions(扩展) 则是让 gh 从一个“工具”进化为“平台”的关键。

gh 遵循了 Unix 哲学,核心二进制文件保持精简,而将特定的、复杂的、社区驱动的功能下放给扩展系统。Extensions 本质上是拥有独立仓库的二进制文件或脚本,它们以 gh- 为前缀,能无缝挂载到 gh 的子命令树下。

全生命周期管理

在开始之前,我们需要掌握扩展的基础管理命令,不要只知道 install。

  • 发现工具:无需去 Google,直接在终端搜索。例如搜索清理工具:gh extension search clean
  • 保持更新:扩展也是软件,需要维护。建议定期执行 gh extension upgrade --all
  • 开发扩展:如果你擅长 Go 或 Shell,可以使用 gh extension create 生成模板,编写自己的专属工作流。

核心扩展实战一:终端里的任务中心 (gh dash)

这也是本章最重量级的推荐。gh dash 是一个基于 TUI (Text User Interface) 的完整仪表盘。它能让你在不打开浏览器、不离开终端的情况下,全键盘操作所有的 PR 和 Issue。

安装

1
gh extension install dlvhdr/gh-dash

启动与界面逻辑

执行 gh dash 后,终端会被划分为三个核心面板:

  1. PRs: 显示所有涉及到你的 PR(你需要 Review 的、你创建的)。
  2. Issues: 显示分配给你的工单。
  3. Repository: 关注的仓库动态。

高频快捷键(Vim 风格)

  • j / k:上下移动光标。
  • Enter:查看详情(会弹出右侧预览窗,展示正文和元数据)。
  • d查看变更 (Diff)。这是最常用的功能之一,按下后进入全屏 Diff 视图,再次按 Esc 退出。
  • o:在浏览器中打开当前选中的项目。
  • c快速检出。直接 Checkout 选中的 PR 到本地,无需查找 ID,看着标题按 c 即可。
  • r:刷新数据。
  • /:在当前视图中搜索过滤。

进阶配置:集成 Delta 美化 Diff

默认情况下,按下 d 键调用的 Diff 视图较为朴素。我们可以通过修改配置文件,将 gh dash 的 Diff 阅读器替换为 Delta(一个带有语法高亮和行内变更显示的 Git 查看器)。

首先确保本地已安装 Delta。然后编辑配置文件 ~/.config/gh-dash/config.yml,添加 pager 字段:

1
2
pager:
diff: delta

保存后重启 gh dash。此时再次选中 PR 并按下 d 键,原本的纯文本 Diff 将变为带有语法高亮、并排对比(Side-by-side)效果的 Delta 视图。

进阶配置:自定义过滤器

gh dash 的强大在于可配置性。你可以通过配置自定义过滤器,将杂乱的 PR 列表整理为有序的任务清单。例如,定义一个“必须立即处理的 Review”部分:

1
2
3
4
5
prSections:
- title: "🔥 Needs My Review"
filters: "is:open review-requested:@me"
- title: "My PRs"
filters: "is:open author:@me"

进阶配置:自定义按键映射

如果默认的快捷键不符合你的习惯,或者你希望添加新的快捷操作,可以在配置文件中的 keybindings 字段进行定义。

例如,将 M 键映射为直接合并(Merge)当前 PR:

1
2
3
4
keybindings:
prs:
- key: M
command: "gh pr merge {{.PrNumber}} --merge --auto"

配置完成后,你的终端仪表盘将变成一个高度定制化的工作台。每天运行 gh dash,即可明确当天的 Review 任务和开发进度,无需频繁切换浏览器。

核心扩展实战二:安全的僵尸分支清理器 (gh poi)

随着项目推进,本地会堆积大量已经 Merge 过的 feature/* 分支。使用 git branch -D 需要逐个确认,极易删错未合并的分支;使用 git branch | grep ... | xargs 又过于粗暴。

gh poi (Point of Interest) 利用 GitHub API 来判断分支状态,提供了安全性与便捷性的平衡。

安装

1
gh extension install seachicken/gh-poi

安全性机制

普通的 Git 命令只能判断本地分支是否 merged 到本地 main。但如果你的本地 main 落后于远程,Git 可能会误判分支未合并。gh poi 会直接向 GitHub API 查询分支在远程仓库的合并状态。只有得到 API 确认的答复,它才会建议删除。

交互式清理流

执行 gh poi,它会扫描本地所有分支,并给出一个交互式列表。

  • Merged 状态的分支会被默认选中。
  • Unmerged 状态的分支会显示警告,防止误删。
  • Space 切换选择,按 Enter 执行批量删除。
  • 清理完成后,它会自动询问是否运行 git remote prune origin,一次性清理本地分支引用和远程追踪引用。

其他高价值扩展推荐

除了上述两个核心扩展,以下工具也能在特定场景提升效率:

扩展名仓库 (gh extension install ...)核心价值
gh copilotgithub/gh-copilotAI 助手。支持 gh copilot suggest "如何撤销最近一次 commit",直接给出 Git 命令解释,无需查阅文档。
gh screensavervilmibm/gh-screensaver视觉组件。在长时间跑脚本等待时,在终端显示 ASCII 风格的屏保(如烟花、弹跳球)。
gh ecok1LoW/gh-eco生态探索。类似于 npm search,可以直接在终端里搜索、浏览所有的 GitHub Actions 和 CLI Extensions。

20.5. 脚本化:基于 gh + jq 的工程化数据流

这是本章的 重头戏,也是区分“使用者”与“专家”的分水岭。

gh 的 CLI 命令看似简单,但其底层通过 --json 参数暴露了 GitHub 完整的 GraphQL/REST API 数据结构。配合 Linux 强大的 JSON 处理神器 jq,我们可以将 GitHub 变成一个可查询、可编程的 实时数据库

在这里,我们不再是在“敲命令”,而是在进行 数据管道的编排

核心工具链准备

工欲善其事,必先利其器。请确保您的终端环境已经存在以下工具:

  • gh: 数据源。
  • jq: 处理器。JSON 领域的 awk
  • xargs: 并发执行器(批量操作必用)。
1
2
3
# windows下载
scoop install jq
gh --version && jq --version

20.5.1. 数据解剖学:理解 JSON 载荷

在编写任何脚本之前,必须先看清“猎物”长什么样。几乎所有的查询命令(pr list, issue list, repo list)都支持 --json

全量字段透视

很多教程只告诉你 --json title,url,但你如何知道还有哪些字段可用?请执行以下命令,获取一个 PR 的 全量元数据

1
gh pr list --limit 1 --json title,number,author,url,createdAt,updatedAt,state,isDraft,mergeable,reviewDecision,statusCheckRollup,reviews,assignees,labels

输出的 JSON 将非常庞大。重点关注以下几个复杂的嵌套对象,它们是脚本化的核心难点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[ 
{
"assignees": [], // 被指派负责处理该 PR 的人员列表,当前为空
"author": { // 包含 PR 创建者(作者)信息的对象
"id": "U_kgDOCsjKXw", // 作者在 GitHub 系统的全局唯一标识符 (Node ID)
"is_bot": false, // 布尔值,标识作者是否为机器人账号,false 表示是真人
"login": "Prorise-cool", // 作者的 GitHub 登录名(用户名)
"name": "" // 作者的公开显示名称(昵称),此处为空字符串
}, // 作者信息对象结束
"createdAt": "2025-12-01T13:01:32Z", // PR 创建的时间,格式为 ISO 8601 (UTC 时间)
"isDraft": false, // 布尔值,标识该 PR 是否为“草稿”状态,false 表示已正式发布
"labels": [], // 该 PR 关联的标签列表(如 bug, enhancement 等),当前为空
"mergeable": "MERGEABLE", // 合并状态,"MERGEABLE" 表示代码无冲突,可以合并
"number": 10, // 该 PR 在当前仓库中的编号(ID),此处为第 10 号
"reviewDecision": "", // 代码审查的最终决定(如 APPROVED, CHANGES_REQUESTED),当前为空
"reviews": [], // 具体的审查记录列表,当前没有审查记录
"state": "OPEN", // PR 的当前状态,"OPEN" 表示开启中(未合并也未关闭)
"statusCheckRollup": [], // CI/CD 状态检查(Status Checks)的汇总结果,当前为空
"title": "feat: add <p> hello world", // PR 的标题,描述了具体的修改内容
"updatedAt": "2025-12-01T13:01:32Z", // 该 PR 最后一次更新的时间 (UTC)
"url": "https://github.com/Prorise-cool/github_action_test/pull/10" // 该 PR 在 GitHub 网页上的完整访问链接
}
]
  • statusCheckRollup: 包含了 CI/CD 的运行结果(是红是绿,哪个 Job 挂了)。
  • reviewDecision: APPROVED, CHANGES_REQUESTEDREVIEW_REQUIRED。这是判断 PR 是否可合并的黄金标准。
  • reviews: 具体的评审记录数组。

jq 基础语法速查(为后续脚本铺垫)

  • .[]: 将数组拆解为独立的行(对象)。
  • select(...): 过滤器,类似 SQL 的 WHERE
  • map(...): 转换器,提取对象中的特定字段。
  • |: 管道,将上一步的结果传递给下一步。

20.5.2. 实战入门:从 JSON 到可用数据的最小闭环

在实际业务环境中,无论是统计团队 KPI 还是清理僵尸数据,核心解法都遵循 “获取 (Query) -> 过滤 (Filter) -> 重组 (Format)” 的固定模式。

我们通过一个高频场景来演练:找出指定作者提交的所有开启状态 PR,并提取其 URL 进行后续处理

命令行组合实战

在终端执行以下命令,这是最基础的数据提取管道:

1
2
gh pr list --state open --json author,title,url | \
jq -r '.[] | select(.author.login == "Prorise-cool") | "标题: \(.title) | 链接: \(.url)"'

逻辑深度解析

1. 数据源获取
命令 gh pr list ... 负责从 GitHub 获取原始数据。这里使用了 --json author,title,url 参数。始终坚持按需请求字段,这能显著降低 API 响应延迟,并减少 jq 处理时的内存消耗。

2. 原始输出处理
参数 -r (raw-output) 是脚本化集成的关键。如果不加此参数,输出的字符串会被双引号包裹(例如 "https://..."),这会导致后续工具无法识别。加上 -r 后,输出变为纯文本,可直接传递给 xargs 或变量。

3. 数组拆解
语法 .[] 用于拆箱。GitHub API 返回的数据结构通常是一个数组。这一步操作将数组展开,把内部的每一个 PR 对象转换为独立的数据行流向下游。

4. 条件过滤
语法 select(.author.login == "Prorise-cool") 用于筛选。只有当对象的 author.login 字段完全匹配指定值时,该行数据才会保留。这是编写业务逻辑的核心位置,可以替换为任何布尔表达式。

5. 数据整形
语法 "标题: \(.title)..." 用于重组输出。这是 jq 的字符串插值语法,它将筛选后的对象字段重新拼接为你需要的最终格式。

自动化脚本编写

单行命令适合临时查询,而复杂的工程化任务需要封装为 Shell 脚本。

以下是一个名为 batch_approve.sh 的脚本示例。它的功能是:批量检索指定用户的所有 Open PR,并逐个询问是否通过代码审查 (Approve)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#!/bin/bash

# 配置目标用户
TARGET_USER="Prorise-cool"

# 检查依赖工具
if ! command -v jq &> /dev/null; then
echo "错误: 未安装 jq,请先安装。"
exit 1
fi

echo "正在获取用户 $TARGET_USER 的所有开启 PR..."

# 1. 获取数据并存入数组
# 使用 base64 编码是为了处理标题中可能包含的空格或特殊字符,防止数组截断
raw_data=$(gh pr list --state open --json number,title,author --limit 50 | \
jq -r ".[] | select(.author.login == \"$TARGET_USER\") | @base64")

# 2. 遍历处理
for item in $raw_data; do
# 解码 JSON 对象
_json=$(echo "$item" | base64 --decode)

# 提取关键字段
pr_number=$(echo "$_json" | jq -r '.number')
pr_title=$(echo "$_json" | jq -r '.title')

echo "----------------------------------------"
echo "发现 PR #$pr_number: $pr_title"

# 3. 交互式确认
read -p "是否批准该 PR? (y/n): " choice
if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
echo "正在批准 PR #$pr_number..."
gh pr review "$pr_number" --approve
echo "✅ 已批准"
else
echo "⏭️ 已跳过"
fi
done

echo "所有任务处理完毕。"

脚本关键点说明

这个脚本解决了单纯使用管道符无法处理的复杂交互场景:

Base64 编码技巧
在 Shell 循环中处理 JSON 是一个常见痛点,因为标题中的空格会破坏 for 循环的分割逻辑。脚本中使用 jq ... | @base64 将每个 JSON 对象编码为一行不含空格的字符串,在循环内部再解码,从而保证了数据的完整性。

命令混合调用

脚本展示了如何将 gh 的查询命令 (gh pr list) 和操作命令 (gh pr review) 结合在一起。前者负责提供数据上下文,后者负责执行具体动作。


20.6. 别名系统:将脚本封装为原生命令

写了这么多脚本,如果每次都要输入 ./monitor_prs.sh 还是很麻烦。gh 的 Alias 系统允许我们将脚本“伪装”成 gh 的原生子命令。

注册 Shell 脚本为别名

假设你把上面的 Dashboard 脚本放在了 ~/scripts/daily_brief.sh

1
2
# 注意开头的感叹号 !,这告诉 gh 调用外部 shell
gh alias set morning '!~/scripts/daily_brief.sh'

从此以后,你只需要在终端输入:

1
gh morning

你就拥有了一个专属的、高度定制的 GitHub 早报命令。这就是 CLI 工具链的终极形态:将复杂的操作封装为简单的指令,建立属于你自己的领域特定语言 (DSL)

至此,你对 GitHub 的掌控力已经远超 90% 的开发者。在下一章,我们将离开纯代码的领域,进入 第二十一章节 项目管理,看看如何用 GitHub Projects 替代 Jira,实现任务与代码的完美联动。