第 9 章 · GitHub
一句话:托管 Git 远程仓库的网站,围绕仓库提供拉取请求、Issue、版本发布和权限控制;
gh是它的官方命令行工具,在终端里完成这些网页操作。 用它还是用别的:开源项目和大多数团队用 GitHub;公司要求代码放在国内或自己的服务器上时用 Gitee 或自建 GitLab,Git 命令一模一样,差别见 9.5 末尾的对照表。 核对版本:gh 2.102,2026-10
9.1 安装与版本
Section titled “9.1 安装与版本”先在 github.com 用邮箱注册账号,邮箱最好和第 7 章 git config --global user.email 设的那个一致。
Windows:
winget install GitHub.climacOS:
brew install ghUbuntu 和 Debian 自带软件源里的 gh 落后官方版本很多,先按 gh 手册里 Linux 安装说明的 Debian 一节添加 GitHub 官方 apt 源(链接见 9.7),再安装:
sudo apt install gh查版本:
gh --version装好后登录一次。命令会依次问:登录 GitHub.com 还是企业版服务器,Git 走 HTTPS 还是 SSH,然后在浏览器里输入终端显示的一次性验证码。选 HTTPS 时它会问要不要让 Git 也用这份登录,选是,以后 git push 不再要密码:
gh auth login令牌存进系统的凭据存储(Windows 凭据管理器、macOS 钥匙串);没有凭据存储的 Linux 服务器上,以明文写在 gh 的配置目录里,见 9.5。
9.2 五分钟概念
Section titled “9.2 五分钟概念”- 远程仓库(Repository):GitHub 上的仓库就是第 7 章说的远程,本地
git clone下来的那份默认把它叫origin。提交、分支、标签都在本地做,git push之后网页上才看得到。 - Fork:把别人的仓库在 GitHub 上复制一份到自己名下。你对原仓库没有写权限,就在自己的 fork 上推分支,原仓库习惯叫上游(upstream)。
- 拉取请求(Pull Request,PR):请求把一个分支合并进另一个分支,可以来自同一仓库,也可以来自 fork。评审意见、CI 检查结果、讨论都挂在 PR 上;PR 没关之前,往这个分支再推提交,PR 会自动更新。
- Issue:记录 bug、需求和任务的条目,每个有编号,如
#12。提交说明或 PR 说明里写Fixes #12,合并后这个 Issue 自动关闭。 - 保护分支(Branch protection)与规则集(Rulesets):给
main这类分支加规则,比如必须走 PR、必须有人批准、CI 必须通过、不许强推。规则集是较新的写法,一套规则可以同时管多个分支,效果与保护分支相同。 - 两种认证方式:HTTPS 地址用个人访问令牌(Personal Access Token,PAT)代替密码,
gh auth login会替你管理这个令牌;SSH 地址用密钥,生成和添加步骤见第 6 章 6.4。同一台机器选一种就够。
9.3 常用命令
Section titled “9.3 常用命令”<所有者>/<仓库> 写成 cli/cli 这样。PR 相关的命令不写编号时,指当前分支对应的那个 PR。表的最后一组在网页上操作,路径按 GitHub 中文文档的写法。
| 任务 | 命令或操作 | 说明 |
|---|---|---|
| 仓库 | ||
| 新建仓库并克隆到本地 | gh repo create <名> --private --clone |
公开仓库把 --private 换成 --public |
| 把本地已有项目建成仓库并推送 | gh repo create <名> --private --source=. --push |
代替第 7 章在网页上建空仓库、加远程、推送那几步 |
| 克隆 | gh repo clone <所有者>/<仓库> |
克隆的是 fork 时自动加上 upstream 远程 |
| Fork 并克隆 | gh repo fork <所有者>/<仓库> --clone |
你的 fork 是 origin,原仓库是 upstream |
| 让 GitHub 上的 fork 跟上上游 | gh repo sync <你>/<仓库> |
只做快进;分叉了要加 --force,fork 上多出的提交会丢 |
| 在浏览器打开当前仓库 | gh browse |
后面加编号打开对应 Issue 或 PR |
| 拉取请求 | ||
| 用提交说明建 PR | gh pr create --fill |
标题和正文取自提交说明,分支还没推送时会先问推到哪 |
| 建草稿 PR | gh pr create --draft --fill |
草稿不能合并,适合边做边看 CI |
| 草稿改为可评审 | gh pr ready |
|
| 请人评审 | gh pr edit --add-reviewer <用户名> |
多人用逗号隔开 |
| 列出打开的 PR | gh pr list |
加 --author "@me" 只看自己的 |
| 和我有关的 PR | gh pr status |
当前分支、我建的、等我评审的,带检查结果 |
| 看 PR 的 CI 检查 | gh pr checks --watch |
一直刷新到全部检查结束 |
| 把别人的 PR 拉到本地试 | gh pr checkout <编号> |
来自 fork 的 PR 也行 |
| 在浏览器看 PR | gh pr view --web |
评审逐行评论在网页上更方便 |
| 批准 | gh pr review <编号> --approve |
|
| 要求修改 | gh pr review <编号> -r -b "<意见>" |
|
| 压成一个提交合并并删分支 | gh pr merge --squash --delete-branch |
本地和远程的分支一起删 |
| Issue | ||
| 新建 | gh issue create --title "<标题>" --body "<内容>" |
不带参数就逐项提问 |
| 列出打开的 | gh issue list |
加 --label bug 只看带这个标签的 |
| 关闭 | gh issue close <编号> --comment "<说明>" |
|
| 合并时自动关闭 | 提交或 PR 说明里写 Fixes #12 |
合并进默认分支才生效;Closes、Resolves 也行 |
| 发布 | ||
| 推送一个标签 | git push origin v1.0 |
打标签的命令见第 7 章 7.3 |
| 建发布,自动生成说明 | gh release create v1.0 --generate-notes |
说明列出上次发布以来合并的 PR |
| 建发布时带上附件 | gh release create v1.0 <文件> --generate-notes |
文件出现在发布页的下载列表里 |
| 给已有发布补传附件 | gh release upload v1.0 <文件> |
同名文件要加 --clobber 才覆盖 |
| Actions(CI) | ||
| 最近的运行记录 | gh run list |
加 --branch <分支> 只看一个分支;写 CI 见第 10 章 |
| 盯着一次运行到结束 | gh run watch |
不写运行编号会让你从列表里选 |
| 认证 | ||
| 看当前登录的账号 | gh auth status |
每个账号一段,标出哪个正在使用 |
| 让 Git 推拉用 gh 的登录 | gh auth setup-git |
登录时没选让 Git 用这份登录的,补这一步 |
| 切换账号 | gh auth switch |
公司号和私人号都登录过时用 |
| 网页上的操作 | ||
| 设保护分支 | Settings → 分支 → 添加经典分支保护规则 | 或 Settings → 规则集 → 新建分支规则集;勾哪些见 9.5 |
| 改默认分支 | Settings → 默认分支名称右侧的切换按钮 → 更新 | PR 默认合并的目标、Fixes #12 生效的分支都跟着变 |
| PR 和 Issue 模板 | .github/PULL_REQUEST_TEMPLATE.md、.github/ISSUE_TEMPLATE/ |
合并进默认分支后,新建 PR 和 Issue 时自动填入 |
| 指定代码负责人 | .github/CODEOWNERS |
改到对应文件的 PR 自动请这些人评审 |
9.4 典型工作流
Section titled “9.4 典型工作流”给开源项目提第一个 PR
Section titled “给开源项目提第一个 PR”你对这个项目没有写权限,所以先 fork 一份,在自己的 fork 上推分支,再从 fork 向原仓库发 PR:
- Fork 并克隆,然后进入克隆出的目录:
gh repo fork <所有者>/<仓库> --clone。 - 确认有两个远程,
origin是你的 fork,upstream是原仓库:git remote -v。 - 开新分支,不要直接在
main上改:git switch -c fix/<名>。 - 改好后提交:
git commit -am "<说明>"。 - 推到自己的 fork:
git push -u origin fix/<名>。 - 发 PR,gh 已把原仓库设为默认仓库,PR 发到它的默认分支:
gh pr create --fill。 - 维护者提了修改意见,改完提交后再推,PR 自动更新:
git push。 - PR 合并后,切回主分支:
git switch main。 - 把上游合并进来的提交拉回本地:
git pull --ff-only upstream main。
GitHub 上的 fork 也要跟上时,再 git push origin main,或者 gh repo sync <你>/<仓库>。
在网页上点 Fork 再 git clone 的,要手动 git remote add upstream <原仓库地址>;第一次 gh pr create 时它会问以哪个仓库为基准,选原仓库。
图里两个仓库都在 GitHub 上:① 到 ③ 是你的操作,代码只进你的 fork;④ 的 PR 从 fork 指向上游,⑤ 由维护者合并;⑥ 是第 9 步,上游的新提交回到本地,下一个分支从这里开始。
团队仓库的日常 PR
Section titled “团队仓库的日常 PR”你有仓库的写权限,不用 fork。接着第 7 章“一天的分支开发”往下走:
- 按第 7 章那个工作流的第 1 到 6 步开分支、提交,最后推送:
git push -u origin feature/<名>。 - 建草稿 PR,CI 开始跑:
gh pr create --draft --fill。 - 等 CI 结果,有失败就改了再推:
gh pr checks --watch。 - CI 全部通过,改为可评审:
gh pr ready。 - 请同事评审:
gh pr edit --add-reviewer <用户名>。 - 同事在自己机器上试运行这个 PR:
gh pr checkout <编号>。 - 同事批准:
gh pr review <编号> --approve。 - 压成一个提交合并,删掉本地和远程的功能分支:
gh pr merge --squash --delete-branch。 - 回到主分支:
git switch main。 - 取回合并结果:
git pull。
squash 合并把功能分支上的零碎提交压成 main 上的一个提交,提交说明默认用 PR 标题,所以 PR 标题要写清楚做了什么。
- 回到主分支:
git switch main。 - 取回最新提交:
git pull。 - 打标签:
git tag -a v1.0 -m "<说明>"。 - 推送标签:
git push origin v1.0。 - 建发布,说明自动列出上次发布以来合并的 PR;
--verify-tag在远程没有这个标签时直接报错,防止 gh 自己在最新提交上新建一个:gh release create v1.0 --generate-notes --verify-tag。 - 上传安装包等附件:
gh release upload v1.0 <文件>。 - 在浏览器里检查发布页:
gh browse --releases。
9.5 配置要点
Section titled “9.5 配置要点”gh 自己的配置文件:
| 配置项 | Windows | macOS | Linux |
|---|---|---|---|
| gh 设置 | %APPDATA%\GitHub CLI\config.yml |
~/.config/gh/config.yml |
~/.config/gh/config.yml |
| 登录过的账号 | %APPDATA%\GitHub CLI\hosts.yml |
~/.config/gh/hosts.yml |
~/.config/gh/hosts.yml |
令牌本身在系统凭据存储里,没有凭据存储时才以明文写进 hosts.yml,这个文件别提交、别拷给别人。值得改的只有两项,用命令改,不用手编辑文件:gh config set git_protocol ssh 让 gh repo clone、gh repo fork --clone 用 SSH 地址(已按第 6 章配好密钥时);gh config set editor "code --wait" 让写 PR 和 Issue 正文时打开 VS Code。
仓库里 .github/ 目录下的文件,合并进默认分支才生效:
| 配置项 | 作用 |
|---|---|
PULL_REQUEST_TEMPLATE.md |
新建 PR 时正文自动填入的模板,文件名不分大小写 |
ISSUE_TEMPLATE/ |
Issue 模板,一个文件一种;.md 是普通模板,.yml 是表单 |
ISSUE_TEMPLATE/config.yml |
blank_issues_enabled: false 禁止不用模板建 Issue |
CODEOWNERS |
一行一条,如 *.js @<用户名>,改到这些文件的 PR 自动请此人评审 |
workflows/ |
GitHub Actions 的流水线文件,见第 10 章 |
保护分支值得开的四项。经典分支保护规则和规则集里的叫法不同,按下表找:
| 要做到 | 经典分支保护规则里勾 | 规则集里勾 | 效果 |
|---|---|---|---|
| 必须走 PR | 合并前需要 Pull Request | 在合并前需要拉取请求 | 谁都不能直接推到 main |
| 至少一人批准 | 要求审批,人数填 1 | 同一项下的需要批准,人数填 1 | 自己批准自己不算 |
| CI 通过才能合并 | 合并前需要通过状态检查 | 要求合并前必须通过状态检查 | 要在列表里选具体的检查名,工作流至少跑过一次后,检查名才会出现在列表里 |
| 禁止强推 | 不勾允许强制推送 | 阻止强制推送 | main 的历史不会被 --force 改写 |
经典规则默认管理员可以绕过,要连自己一起管,再勾“不允许绕过上述设置”。
最小的 .github/PULL_REQUEST_TEMPLATE.md,注释在 PR 页面上不显示:
## 改了什么<!-- 一两句话,评审的人先看这里 -->
## 为什么<!-- 关联的 Issue 写 Fixes #编号,合并后自动关闭 -->
## 怎么验证<!-- 跑了哪些测试,或手动点了哪几步 -->
- [ ] 本地测试通过 <!-- 勾选框,评审前自己打勾 -->换到 GitLab 或 Gitee,Git 命令和本章的流程都一样,只是名字和工具不同:
| GitHub | GitLab | Gitee |
|---|---|---|
| 拉取请求(Pull Request,PR) | 合并请求(Merge Request,MR) | Pull Request |
GitHub Actions,配置在 .github/workflows/ |
GitLab CI/CD,配置在 .gitlab-ci.yml |
Gitee Go 流水线 |
| Issue | Issue | Issue |
| Release | Release | 发行版(Release) |
命令行工具 gh |
命令行工具 glab |
无官方命令行工具 |
9.6 注意事项
Section titled “9.6 注意事项”git push要密码,输入 GitHub 登录密码后报Support for password authentication was removed。 原因:GitHub 不接受账号密码做 Git 认证。处理:gh auth login后运行gh auth setup-git;或在密码处粘贴个人访问令牌;或改用 SSH 地址,见第 6 章 6.4。remote: Permission to <所有者>/<仓库>.git denied to <另一个用户名>.原因:Git 用了另一个 GitHub 账号的凭据,常见于公司号和私人号混用。处理:gh auth status看当前账号,gh auth switch切换;Windows 上再到凭据管理器删掉git:https://github.com那一条。- PR 里出现几十个不是你写的提交。 原因:基准分支选错,或者功能分支是从很久没更新的本地
main开出来的。处理:基准分支错了用gh pr edit --base main;否则git fetch upstream,git rebase upstream/main,再git push --force-with-lease。 - fork 页面显示落后上游很多个提交(
commits behind)。 原因:fork 之后不会自动跟随上游。处理:gh repo sync <你>/<仓库>;本地分支用git fetch upstream后git rebase upstream/main。 - 说明里写了
Fixes #12,PR 合并了,Issue 还开着。 原因:只有合并进默认分支才会自动关闭,这个 PR 合进了develop这类分支。处理:手动gh issue close 12;以后在发往默认分支的 PR 里写。 - push 被拒,
remote: error: GH001: Large files detected.原因:GitHub 拒收超过 100 MiB 的单个文件,50 MiB 以上就会警告。处理:大文件改用 Git LFS,git lfs track "*.psd";已经在历史里的,按第 8 章 8.4 撤销表从历史中删掉再推。 - 开了保护分支后,自己
git push origin main也被拒,GH006: Protected branch update failed。 原因:预期行为,规则对有写权限的人一样生效;规则集报的是GH013: Repository rule violations found。处理:开分支走 PR,见 9.4。 - 提交在 GitHub 上显示灰色默认头像,没链接到你的账号。 原因:提交里的
user.email不是 GitHub 账号里登记的邮箱。处理:按第 7 章 7.4 改user.email;或在 GitHub 账号设置里添加这个邮箱,旧提交也会关联上。
9.7 深入阅读
Section titled “9.7 深入阅读”- GitHub 文档(中文):仓库、拉取请求、Actions、账号和认证的官方说明,有中文。
- GitHub CLI 手册:gh 每条子命令的用法和参数,安装一节里有 Linux 的官方 apt 源。
- 拉取请求:建 PR、评审、合并方式和解决冲突,有中文。
- 关于受保护分支:保护分支每一项规则的含义,以及和规则集的关系。
- GitLab 文档:合并请求、GitLab CI/CD 和 glab 命令行工具。
- Gitee 帮助中心:Gitee 的 Pull Request、Issue、发行版和 Gitee Go 流水线。