GitHub 进阶教程 —— Issues、Actions、Releases、分支保护
接续《Git使用教程.md》《Git进阶教程.md》的 GitHub 平台进阶内容 基于
D:\desktop\double_car\项目的实战场景 远程仓库:git@github.com:forest-wang-sunshine/double_car.git整理时间:2026-05-04
📑 目录
- 阶段 8:GitHub 平台功能全景
- 8.1 Issues —— 任务追踪与协作中心
- 8.2 Actions —— CI/CD 自动化
- 8.3 Releases —— 版本发布
- 8.4 分支保护规则 —— 让 main 真正安全
- 综合实战:从 Issue 到 Release 的完整生命周期
- GitHub 其他实用功能(速览)
- 速查表
- 一页纸总结
阶段 8:GitHub 平台功能全景
到这一阶段为止,你已经把 GitHub 当作”代码备份云盘”用得很顺。但 GitHub 真正的价值是它是一个完整的项目协作平台,下面这张图能让你看到全貌:
┌──────────────────────────────────────────────────────────────────┐│ GitHub 仓库(Repository) │├──────────────────────────────────────────────────────────────────┤│ ││ Code ←── 你已经在用:放代码、看文件、看历史 ││ ││ Issues ←── 8.1:任务/Bug 追踪面板 ││ │ ││ └─ 关联 ──→ Pull Requests (你已会) ││ │ ││ └─ 触发 ──→ Actions (8.2 自动化) ││ │ ││ └─ 产出 ──→ Releases ││ (8.3 发布) ││ ││ Settings ──→ Branches ──→ Branch Protection (8.4 保护规则) ││ ││ 其他:Discussions / Projects / Wiki / Pages / Insights ││ │└──────────────────────────────────────────────────────────────────┘一句话总结四个功能:
| 功能 | 一句话价值 |
|---|---|
| Issues | ”记下要做的事和发现的 bug” |
| Actions | ”事情发生时自动跑一段脚本” |
| Releases | ”正式发布一个版本,并附上构建产物” |
| Branch Protection | ”禁止任何人直接污染 main 分支” |
8.1 Issues —— 任务追踪与协作中心
8.1.1 什么是 Issue
Issue = 一张工单。任何”需要做但还没做”的事都可以变成一个 Issue:
- 🐞 发现了 bug:
后车在低速时编码器读数跳变 - ✨ 想加新功能:
增加超声波避障模块 - 📚 文档要补:
README 的硬件接线表缺 IPS200 - ❓ 有疑问要讨论:
PID 参数调到 1.7 之后是否还需要积分项? - 🔧 重构想法:
element_manager 的 64 槽位机制可否抽象出 base 类型
每个 Issue 有唯一编号(如 #3),永久存在仓库里,方便追溯。
8.1.2 Issue 的核心字段
打开任意一个 Issue,能看到这些字段:
┌────────────────────────────────────────────────────────────────┐│ Title: 后车低速时编码器读数跳变 ││ #3 Open / Closed │├────────────────────────────────────────────────────────────────┤│ ││ Description (markdown): ││ 现象:当 PWM duty < 5% 时,编码器 count 偶发跳变 ±2 ││ 复现步骤:1. ... 2. ... ││ 猜测原因:可能是脉冲计数中断的去抖逻辑漏掉了双沿 ││ ││ ──── 评论区 ──── ││ forest: 我看了下 PIT_Demo.c:142,确实没有去抖 ││ others: 建议加 RC 软件滤波再上滑动平均 ││ │├────────────────────────────────────────────────────────────────┤│ Sidebar(右侧栏): ││ Assignees: @forest-wang-sunshine ││ Labels: bug, back-car, priority/high ││ Milestone: v1.1 ││ Linked PR: #5 ││ Projects: 双车开发看板 │└────────────────────────────────────────────────────────────────┘8.1.3 创建一个 Issue
- 仓库主页顶部菜单点 Issues 标签
- 右上角点
New issue - 填 Title(一句话能让人 5 秒看懂的标题)
- 填 Description(markdown 格式,能贴代码、图片、链接)
- 右侧栏填可选字段(Labels、Assignees、Milestone)
- 点
Submit new issue
好 Issue 标题的格式: [模块] 现象 - 关键信息
👍 后车低速编码器跳变(duty < 5% 时偶发 ±2)👍 [front] 环岛识别在反向出环时误判为十字👍 添加根目录 README
👎 bug (太空)👎 这里有问题 (没说哪里)👎 急 急 急 (没信息)8.1.4 Issue 与 PR 联动(关键技巧!)
GitHub 内置了一套关键字魔法:在 commit 信息或 PR 描述里写这些关键字,合并时会自动关闭对应 Issue:
| 关键字 | 含义 |
|---|---|
close / closes / closed | 关闭 Issue |
fix / fixes / fixed | 修复 Issue(同样关闭) |
resolve / resolves / resolved | 解决 Issue(同样关闭) |
用法示例:
docs: 添加项目根目录 README
GitHub 仓库主页之前是空的,本 PR 添加 README 作为门面入口。
closes #2当这个 PR 合并到 main 时,Issue #2 会自动从 Open 变成 Closed。
也支持跨仓库引用:closes user/repo#3。
一次关多个 Issue
fixes #5, fixes #7, fixes #9⚠️ 注意: 必须每个 Issue 前都写关键字。fixes #5, #7, #9 ❌ 这样只会关 #5。
8.1.5 Issue 模板(让仓库专业起来)
如果你的仓库有人提 Issue,模板能让对方按你预期的格式提交,避免”问题描述很模糊”。
创建模板
- 在仓库根目录创建
.github/ISSUE_TEMPLATE/目录 - 添加模板文件,比如
bug_report.md:
---name: Bug 报告about: 反馈一个发现的 bugtitle: '[BUG] 'labels: bugassignees: ''---
## 现象描述实际看到的现象
## 期望行为描述应该是怎样的
## 复现步骤1. ...2. ...3. ...
## 环境- 硬件: TC264D 主控板 vX.X- 编译器: TASKING vX.X- 摄像头: MT9V03X- 是否能稳定复现: 是 / 偶发 1/X 次
## 相关日志/截图(贴 logic analyzer 波形、串口输出、屏幕截图等)下次有人点 New issue,会先弹出”选择模板”页面,选择后预填这些字段。
也能写功能请求模板
.github/ISSUE_TEMPLATE/feature_request.md:
---name: 功能请求about: 提议一个新功能title: '[FEAT] 'labels: enhancement---
## 想解决什么问题
## 期望的解决方案
## 替代方案
## 影响哪些模块- [ ] front_car- [ ] back_car- [ ] 共享库8.1.6 Labels、Milestones、Assignees
Labels(标签)
GitHub 默认给了几个:bug、documentation、enhancement、good first issue、help wanted、question。
给本项目设计一套合适的标签(按维度分类):
类型 (type) 模块 (scope) 优先级 (priority) bug front-car priority/critical enhancement back-car priority/high documentation common priority/medium question drivers priority/low refactor docs
状态 (status) 领域 (area) status/blocked area/perception status/in-progress area/control status/needs-review area/persistence area/hardware设置位置:Issues 标签页 → Labels 按钮 → New label。
颜色按维度配——比如所有 priority/* 用红/橙/黄/绿渐变,看一眼就知道紧急程度。
Milestones(里程碑)
把多个 Issue 打包成”v1.1 大目标”。比如:
Milestone: v1.1 - 后车闭环加固 Due date: 2026-06-01 Description: 后车跟随稳态精度提升 + 速度匹配收敛性问题
Issues 列表: #5 后车低速编码器跳变 [closed] #7 速度匹配 SMC 抖振抑制 [open] #9 卡尔曼初值收敛慢 [open]
Progress: ▓▓░░░ 33% (1/3)设置位置:Issues 标签页 → Milestones → New milestone。
Assignees(指派人)
谁负责处理这个 Issue。点 Issue 右侧 Assignees 选人。一个 Issue 可以多人指派。
8.1.7 实战:在 double_car 创建一个 Issue 看看
练习任务(自己操作,不在终端跑):
- 打开 https://github.com/forest-wang-sunshine/double_car/issues
- 点
New issue - 标题:
docs: 添加 GitHub 进阶教程笔记 - 描述:
## 内容整理 GitHub 平台进阶功能的学习笔记,包括:- Issues- Actions- Releases- 分支保护规则## 目的作为日常协作和发布流程的参考资料完成后将提交一个 PR 添加 `GitHub进阶教程.md` 文件。
- 创建后记下 Issue 编号(比如
#3) - 后面发 PR 时在描述里写
closes #3,合并时 Issue 自动关闭
8.2 Actions —— CI/CD 自动化
8.2.1 什么是 CI/CD
- CI = Continuous Integration(持续集成)—— 每次 push/PR,自动跑测试和检查
- CD = Continuous Deployment/Delivery(持续部署/交付)—— 测试通过后自动发布
开发者 push 代码 ───→ GitHub 检测到事件 │ ▼ ┌──────────────┐ │ 触发 CI │ │ │ │ 跑 lint │ │ 跑测试 │ │ 跑构建 │ └──────┬───────┘ │ ┌───────┴───────┐ ▼ ▼ 全绿 ✅ 有红 ❌ │ │ 允许合并 PR 阻止合并 + 通知开发者CI/CD 的价值: 把”跑测试”这种重复劳动从人脑挪到机器,并且每次都跑完整套,不会漏。
8.2.2 GitHub Actions 的核心概念
Workflow(工作流) 一个完整的自动化流程 │ ├── Trigger 什么时候触发(on) │ └── Job(s) 一个或多个 job │ ├── runs-on 在什么环境运行 │ └── Step(s) 具体的步骤 │ ├── uses 用别人写好的 action │ └── run 跑一段 shell 命令对应中文: 工作流 → 作业 → 步骤。一个仓库可以有多个工作流,每个工作流可以有多个作业,每个作业可以有多个步骤。
8.2.3 workflow 文件结构详解
Workflow 文件必须放在 .github/workflows/ 目录下,扩展名 .yml。
最小可运行模板
name: Hello CI # 工作流名字(在 Actions 页面显示)
on: # 触发条件 push: # push 时触发 branches: [main] # 仅 main 分支 pull_request: # PR 时触发 branches: [main] # 目标是 main 的 PR
jobs: # 作业列表 greet: # 作业 ID runs-on: ubuntu-latest # 在 Ubuntu 容器里跑
steps: # 步骤列表 - name: Say hello run: echo "Hello from GitHub Actions!"
- name: Print environment run: | uname -a pwd ls -la把这个文件 commit 推上去,下一次 push 就会自动跑。
8.2.4 常用触发条件(on)
on: push: # push 时 branches: [main, develop] # 限定分支 paths: # 限定路径 - 'src/**' - '!**.md' # ! 表示排除
pull_request: # PR 时(推荐 CI 都监听这个) branches: [main] types: [opened, synchronize, reopened] # PR 的子事件
schedule: # 定时触发(cron 语法) - cron: '0 8 * * 1' # 每周一上午 8 点
workflow_dispatch: # 允许手动触发(Actions 页面有按钮) inputs: version: description: '要发布的版本' required: true default: 'v1.0.0'
release: # 发 release 时 types: [published]
issue_comment: # 有人评论 Issue 时 types: [created]8.2.5 常用步骤(steps)
steps: # 1. 拉取代码(几乎每个 workflow 第一步都是它) - uses: actions/checkout@v4
# 2. 设置语言环境 - uses: actions/setup-node@v4 with: node-version: '20'
- uses: actions/setup-python@v5 with: python-version: '3.12'
# 3. 缓存(加速后续构建) - uses: actions/cache@v4 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
# 4. 跑命令 - name: Install dependencies run: npm ci
- name: Run tests run: npm test
# 5. 多行命令 - name: Build and check run: | make build ls -la build/ du -sh build/
# 6. 设置环境变量 - name: Set env run: echo "MY_VAR=hello" >> $GITHUB_ENV
# 7. 用环境变量 - run: echo "Var is $MY_VAR"
# 8. 上传产物(让别的 job 或人下载) - uses: actions/upload-artifact@v4 with: name: firmware-hex path: Debug/*.hex8.2.6 实战 1:检查 commit 信息格式(Conventional Commits)
本项目 CLAUDE.md 规定 commit 必须遵循 Conventional Commits。手动 review 容易漏,让 Actions 自动检查:
name: Lint commit messages
on: pull_request: branches: [main]
jobs: commitlint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # 拉取完整历史,否则比对不了
- uses: actions/setup-node@v4 with: node-version: '20'
- name: Install commitlint run: | npm install --save-dev @commitlint/cli @commitlint/config-conventional
- name: Configure commitlint run: | cat > commitlint.config.js << 'EOF' module.exports = { extends: ['@commitlint/config-conventional'], rules: { 'type-enum': [2, 'always', [ 'feat', 'fix', 'docs', 'style', 'refactor', 'test', 'chore', 'perf' ]] } }; EOF
- name: Validate PR commits run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose效果:以后任何人发 PR,commit 信息不符合 feat: xxx / fix(scope): xxx 格式,CI 直接红,不能合并。
8.2.7 实战 2:检查不能提交编译产物
防止有人误把 .elf / .hex / Debug/ 提交进仓库(虽然 .gitignore 有,但保险起见):
name: Forbid binary artifacts
on: pull_request: branches: [main]
jobs: check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Check for forbidden files run: | forbidden_patterns=( "*.elf" "*.hex" "*.bin" "*.map" "*.o" "Debug/*" "Release/*" "*.zip" )
found=0 for pattern in "${forbidden_patterns[@]}"; do if find . -path './.git' -prune -o -type f -name "$pattern" -print | grep -q .; then echo "❌ 发现禁止提交的文件类型: $pattern" find . -path './.git' -prune -o -type f -name "$pattern" -print found=1 fi done
if [ $found -eq 1 ]; then echo "" echo "请检查 .gitignore 并删除上述文件后重新提交" exit 1 fi
echo "✅ 没有发现违规文件"8.2.8 实战 3:markdown 文档格式检查
name: Markdown Lint
on: pull_request: paths: - '**.md'
jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: DavidAnson/markdownlint-cli2-action@v15 with: globs: '**/*.md' config: | { "MD013": false, "MD041": false }8.2.9 实战 4:自动给 PR 打标签
PR 改了哪些文件,自动加对应标签:
name: PR Labeler
on: pull_request_target: types: [opened, synchronize]
jobs: label: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - uses: actions/labeler@v5配套的规则文件 .github/labeler.yml:
front-car: - changed-files: - any-glob-to-any-file: 'Front_Car-main/**'
back-car: - changed-files: - any-glob-to-any-file: 'back_car-main/**'
documentation: - changed-files: - any-glob-to-any-file: ['**/*.md', 'docs/**']
ci: - changed-files: - any-glob-to-any-file: '.github/**'效果:以后 PR 改了 Front_Car-main/code/PID.c,自动加上 front-car 标签,一眼能看出来 PR 影响范围。
8.2.10 Secrets(密钥管理)—— 别把密码塞进 yml!
如果你的 workflow 需要 API 密钥(比如调云服务),绝对不要写在 yml 里(会被全世界看到)。
设置 Secret
- 仓库 Settings → 左侧 Secrets and variables → Actions
- 点 New repository secret
- 填 Name(如
MY_API_KEY)和 Value - 保存后这个值永远只能引用,不能再查看
在 workflow 里用
- name: Call API env: API_KEY: ${{ secrets.MY_API_KEY }} run: | curl -H "Authorization: Bearer $API_KEY" https://api.example.com/...GitHub 会自动把 secret 在日志里 mask 成 ***,避免泄漏。
8.2.11 关于 AURIX 项目的特殊情况
⚠️ TASKING 编译器不能在 GitHub-hosted runner 上运行:
- License 是商业的,不能装在公共 runner 上
- AURIX Studio 是 Windows GUI,不适合 headless CI
折中方案
方案 A:纯 lint,不编译
- 跑 commit message 检查、文档拼写、引脚冲突检查、文件结构验证等
- 依然能拦住 80% 的低级错误
方案 B:self-hosted runner(自建 runner)
把你装了 TASKING 的 Windows 电脑配置成 GitHub 的 self-hosted runner,让 Actions 在你的电脑上跑。
设置位置:Settings → Actions → Runners → New self-hosted runner。
按 GitHub 给的 PowerShell 脚本一步步装好,然后 workflow 里写:
jobs: build: runs-on: self-hosted # ← 不再用 ubuntu-latest steps: - uses: actions/checkout@v4 - run: | # 这里就能用 TASKING 命令了 cd Front_Car-main/Debug mingw32-make⚠️ self-hosted runner 的安全问题:仓库公开时不要用 self-hosted runner(fork 提 PR 能在你电脑上跑任意代码)。私有仓库或团队成员可信时再用。
适合本项目的简易方案
写一个只检查不编译的 CI,先把质量门槛立起来:
name: CI
on: pull_request: branches: [main] push: branches: [main]
jobs: lint: name: Format & Lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Check no binary files run: | if find . -path './.git' -prune -o \ \( -name '*.elf' -o -name '*.hex' -o -name '*.map' \) \ -print | grep -q .; then echo "::error::发现编译产物" exit 1 fi
- name: Check both projects exist run: | test -d Front_Car-main/code || (echo "Front_Car-main/code 缺失"; exit 1) test -d back_car-main/code || (echo "back_car-main/code 缺失"; exit 1)
- name: Validate zf_common_headfile.h discipline run: | # 检查没有 .h 文件违反"不能 #include zf_common_headfile.h"的规则 if grep -r --include='*.h' '#include "zf_common_headfile.h"' \ Front_Car-main/code back_car-main/code 2>/dev/null; then echo "::error::用户层 .h 不应该包含 zf_common_headfile.h(会循环包含)" exit 1 fi注意 ::error:: 是 GitHub Actions 的特殊语法,会让这条信息变红色错误并定位到 PR。
8.3 Releases —— 版本发布
8.3.1 Release 与 Tag 的关系
先搞清楚两个相关概念:
Tag Release─────────── ──────────────Git 原生概念 GitHub 平台功能是某个 commit 的"别名标签" 基于 Tag 包装的"发布页面"轻量、纯本地能创建 带描述、附件、下载统计git tag v1.0.0 必须先有 Tag,再创建 Release 网页操作或 API 创建关系图:
●────●────●────●────● ← main ↑ ↑ v1.0.0 v1.1.0 │ │ │ │ │ (Release 页面) │ 含描述、Release Notes │ 含附件 .hex / .elf │ 含下载统计 │ (Tag,纯指针)8.3.2 语义化版本(SemVer)
行业标准的版本号格式:
v <主版本>.<次版本>.<修订版本>v MAJOR . MINOR . PATCH| 数字 | 含义 | 什么时候 +1 |
|---|---|---|
| MAJOR | 主版本 | 不向前兼容的大改动 |
| MINOR | 次版本 | 添加新功能,向前兼容 |
| PATCH | 修订版本 | 修 bug,向前兼容 |
例子:
v1.0.0→v1.0.1:修了一个 bugv1.0.1→v1.1.0:加了一个新功能(如新增超声波避障)v1.1.0→v2.0.0:重构了整个控制框架,老代码不兼容
预发布版本: v2.0.0-alpha.1、v2.0.0-rc.1(rc = release candidate)
8.3.3 通过命令行创建 Tag
# 1. 轻量 tag(仅指针,没 message)git tag v1.0.0
# 2. 带注解 tag(推荐,包含作者、时间、message)git tag -a v1.0.0 -m "v1.0.0 - 首个稳定版
主要功能:- 前车循迹(环岛/十字/斑马线)- 后车跟随(卡尔曼+SMC)- 双车通信(红外)"
# 3. 给历史某个 commit 打 taggit tag -a v0.9.0 95ac857 -m "v0.9.0 - 比赛前最后一个版本"
# 4. 推送 tag 到远程(默认 push 不推 tag)git push origin v1.0.0
# 5. 一次推所有本地 taggit push origin --tags
# 6. 查看所有 taggit tag # 列表git tag -l "v1.*" # 通配符过滤git show v1.0.0 # 看某 tag 的详情
# 7. 删除 taggit tag -d v1.0.0 # 删本地git push origin --delete v1.0.0 # 删远程8.3.4 在 GitHub 网页创建 Release
方式 A:从已有 Tag 创建
- 仓库主页右侧 Releases → 点进入
- 点
Draft a new release - Choose a tag 下拉选已有 tag(或填新名让它自动建)
- Target 选基于哪个分支(默认 main)
- Release title:
v1.0.0 - 首个稳定版 - Description:详细的 Release Notes(看下面 8.3.5)
- Attach binaries:拖拽
.hex/.elf等文件到这里(可选) - 选项:
- Set as a pre-release:alpha/beta/rc 时勾上
- Set as the latest release:标记为”最新版”
- Create a discussion for this release:自动开一个讨论区
- 点
Publish release
方式 B:从命令行(用 gh CLI)
如果你装了 GitHub CLI(gh),可以一行搞定:
gh release create v1.0.0 \ --title "v1.0.0 - 首个稳定版" \ --notes-file RELEASE_NOTES.md \ Front_Car-main/Debug/Front_Car.hex \ back_car-main/Debug/Back_Car.hex8.3.5 Release Notes 写法
推荐格式
## 🎯 主要内容
首个比赛稳定版本,覆盖完整的前车循迹和后车跟随能力。
## ✨ 新功能
- 前车环岛识别状态机(左/右环岛)- 前车十字识别与十字穿越- 前车斑马线识别(终点判停)- 后车双目标连通域追踪- 后车 SMC + 卡尔曼速度匹配
## 🐞 修复
- 修复后车低速时编码器读数跳变(#5)- 修复前车出环误判十字(#7)
## 🔧 改进
- PID 改用 LADRC 提升抗扰动- 电压补偿前移,避免 ADC 噪声直接调制 PWM
## 📚 文档
- 添加 README、Git使用教程、Git进阶教程- 完善 Project_Interview_Mastery.md 的算法推导
## 💔 不兼容变更
无(首个版本)
## 📦 下载
- `Front_Car.hex` —— 前车固件,烧到前车 TC264D- `Back_Car.hex` —— 后车固件,烧到后车 TC264D
## 🧪 测试
- ✅ 前车单车跑完赛道(5/5)- ✅ 后车单车跟前车跑完赛道(5/5)- ✅ 双车协作完整赛道(3/3)
## 👥 贡献者
@forest-wang-sunshine自动生成 Release Notes
GitHub 网页创建 Release 时,点 Generate release notes 按钮,GitHub 会自动从上次 Release 到当前 tag 之间的所有 PR 列出来,按 label 分类,生成一份初稿。
可以配置自定义模板:.github/release.yml
changelog: exclude: labels: - ignore-for-release categories: - title: ✨ 新功能 labels: [enhancement, feat] - title: 🐞 Bug 修复 labels: [bug, fix] - title: 📚 文档 labels: [documentation] - title: 🔧 维护 labels: [chore, refactor]8.3.6 实战:Tag 触发 Actions 自动构建并附 .hex
最强工作流:开发完成 → 打 tag → push → GitHub Actions 自动编译 → 自动创建 Release 并附固件。
name: Release
on: push: tags: - 'v*' # 只在打 v 开头的 tag 时触发
jobs: build: runs-on: self-hosted # 需要本机 TASKING(见 8.2.11) steps: - uses: actions/checkout@v4
- name: Build front car run: mingw32-make -C "Front_Car-main/Debug"
- name: Build back car run: mingw32-make -C "back_car-main/Debug"
- name: Collect artifacts run: | mkdir release-files cp "Front_Car-main/Debug/Front_Car.hex" release-files/ cp "back_car-main/Debug/Back_Car.hex" release-files/ cp "Front_Car-main/Debug/Front_Car.elf" release-files/ cp "back_car-main/Debug/Back_Car.elf" release-files/
- name: Create Release uses: softprops/action-gh-release@v2 with: generate_release_notes: true # 自动生成 release notes files: | release-files/*.hex release-files/*.elf效果:
# 你的工作流变成只需要:git tag -a v1.0.0 -m "v1.0.0 - 首个稳定版"git push origin v1.0.0
# GitHub 自动:# 1. 检测到 v1.0.0 tag# 2. 触发 release.yml workflow# 3. 在 self-hosted runner 上编译两个项目# 4. 创建 v1.0.0 Release 页面# 5. 自动生成 release notes(从上次 release 到这个 tag 的所有 PR)# 6. 附上 4 个二进制文件# 7. 通知所有 watchers8.3.7 删除/修改 Release
- 改 release notes:去 Release 页面点
Edit - 删除 release:Release 页面 →
...→Delete⚠️ 删除 release 不会删 tag,要单独git push origin --delete v1.0.0 - 取消 latest 标记:Edit release → 取消
Set as the latest release
8.4 分支保护规则 —— 让 main 真正安全
8.4.1 为什么需要保护规则
到目前为止,你或任何 collaborator 都可以直接 git push origin main,绕过 PR 流程。这在团队里是大问题:
- 实习生手滑 force push,main 历史被改写
- 没 review 的烂代码直接进 main
- 没跑 CI 的代码进 main,触发线上故障
- 不该 merge 的实验代码进 main
分支保护规则 = 让 GitHub 帮你强制执行规矩。设置后即使是仓库 owner 也得遵守(除非显式给 owner 豁免)。
8.4.2 在哪里设置
仓库主页 → Settings → 左侧 Branches → 右侧 Add branch protection rule或者用新版的 Rulesets(GitHub 在 2023 年后推荐用这个):
仓库主页 → Settings → Rules → Rulesets → New ruleset两者功能类似,Rulesets 更灵活,能批量管理多分支。新手先用 Branch protection rules 也完全没问题。
8.4.3 关键开关详解
打开 Add branch protection rule,Branch name pattern 填 main(或用通配符 release/*、main 同时保护)。然后看下面这些开关:
Require a pull request before merging(必开)
强制:所有改动必须通过 PR,不能直接 push 到 main。
子选项:
- Require approvals —— 至少需要几个人 review 同意。个人项目可填 0,团队建议 1+
- Dismiss stale pull request approvals when new commits are pushed —— 有新 commit 时,旧的 approve 自动失效(防止”批了又改”)
- Require review from Code Owners —— 见 8.4.4
Require status checks to pass before merging(强烈建议开)
强制:CI 必须全绿才能合并。
设置后会出现一个搜索框,让你勾选必须通过的 check:
☑ commitlint ← 必须通过☑ markdown-lint ← 必须通过☑ no-binary ← 必须通过☑ ci / lint ← 必须通过子选项:
- Require branches to be up to date before merging —— 强制 PR 分支必须是基于最新的 main(防止过时分支引入兼容性问题)
Require conversation resolution before merging
PR 评论里所有”未解决”的对话必须点 Resolve 才能合并。防止 reviewer 提的问题被忽略。
Require signed commits
要求 commit 有 GPG 签名(证明真的是你的)。安全要求高的项目开。
Require linear history
禁止合并提交,只允许 squash merge 或 rebase merge。让历史保持一条直线。
Require deployments to succeed before merging
如果你用 GitHub 的 Environments(如 staging),强制部署到 staging 成功才能合并。
Lock branch
完全锁住,任何人都不能改。适合归档已结束的项目。
Do not allow bypassing the above settings
最严格——连 admin 都不能绕过。强烈建议开,否则规则等于摆设。
Restrict who can push to matching branches
限定特定的人/团队才能 push。即使开了上面的所有规则,可能还想精确控制谁能 merge。
危险操作禁止
- Allow force pushes ⚠️ —— 务必关掉!force push 能改写历史
- Allow deletions ⚠️ —— 务必关掉!防止有人删 main 分支
8.4.4 Code Owners 文件
CODEOWNERS 文件让 GitHub 自动给 PR 指定 reviewer。
创建 CODEOWNERS
文件路径:.github/CODEOWNERS(推荐位置)
内容示例:
# 默认所有改动都要 owner review* @forest-wang-sunshine
# 前车代码归 forest 管/Front_Car-main/ @forest-wang-sunshine
# 后车代码归后车小组/back_car-main/ @backcar-team-member
# 文档归文档维护者管*.md @docs-maintainer/docs/ @docs-maintainer
# CI 配置归 DevOps/.github/ @devops-lead效果:
- PR 改了
Front_Car-main/code/PID.c,自动 @forest-wang-sunshine来 review - PR 改了
README.md,自动 @docs-maintainer - 一个 PR 改了多个区域,会 @ 所有相关 owner
如果保护规则开了 Require review from Code Owners,这个 review 还是必须的。
8.4.5 实战配置建议
个人项目(如本项目)
Branch name pattern: main☑ Require a pull request before merging ☐ Require approvals (0 个,因为只有一个人)☑ Require status checks to pass ☑ Require branches to be up to date 勾选: 你的 CI workflow 名字☑ Require conversation resolution☑ Do not allow bypassing the above settings☐ Allow force pushes☐ Allow deletions效果:仍然能强制走 PR 流程,CI 必须通过,但因为只有自己一个人,不需要别人 approve。
小团队项目
Branch name pattern: main☑ Require a pull request before merging ☑ Require approvals: 1 ☑ Dismiss stale pull request approvals when new commits are pushed ☑ Require review from Code Owners☑ Require status checks to pass ☑ Require branches to be up to date 勾选: 所有关键 CI workflow☑ Require conversation resolution☑ Do not allow bypassing the above settings☐ Allow force pushes☐ Allow deletions大型/严肃项目
在小团队基础上加:
☑ Require approvals: 2☑ Require signed commits☑ Require linear history☑ Require deployments to succeed before merging☑ Restrict who can push → 限定特定团队8.4.6 Rulesets(GitHub 2023+ 新功能)
Rulesets 是 Branch protection rules 的升级版,主要优势:
- Bypass list —— 精确指定谁能绕过(按用户、团队、role)
- 多分支模式 —— 一个 ruleset 同时保护
main、release/*、production等 - 可启用/禁用切换 —— 临时关闭整套规则比删了重建方便
- 审计日志 —— 谁绕过了规则、什么时候,都有记录
设置入口:Settings → Rules → Rulesets → New ruleset → New branch ruleset。
填表:
Name: Protect main and releasesEnforcement status: Active
Targets: Branches: main, release/*
Rules: ☑ Restrict creations ☑ Restrict updates → 必须通过 PR ☑ Restrict deletions ☑ Require linear history ☑ Require pull request - Required approvals: 1 - Require Code Owner review ☑ Require status checks to pass - commitlint - ci/lint ☐ Block force pushes如果将来你的项目变大了,迁移到 Rulesets 体验更好。
综合实战:从 Issue 到 Release 的完整生命周期
把今天学的所有功能串起来,看一个真实场景如何流转:
场景
某天你测试时发现:后车在过弯时偶尔丢失目标,导致追丢前车。
第 1 步:开 Issue
去仓库 Issues 页面,New issue:
Title: 后车过弯时偶发丢失目标,追丢前车
Description:## 现象后车在大弯道(半径 < 1.2m)时,连通域追踪偶尔丢失双目标,导致 error[0]/error[1] 异常,后车失控停车或冲出赛道。
## 复现步骤1. 双车正常跟随直道2. 进入第 3 圈的大左弯3. 大约 30% 概率丢目标
## 猜测原因弯道时前车从摄像头视野的一侧滑到中间,连通域算法可能把前车的车标和阴影分成两个独立连通域。
## 影响比赛 3 圈中至少出现 1 次,致命问题
Labels: bug, back-car, priority/criticalAssignees: @forest-wang-sunshineMilestone: v1.0.1提交后得到 Issue 编号 #5。
第 2 步:基于 Issue 开发
git switch main && git pullgit switch -c fix/back-car-target-loss改 back_car-main/code/image_deal.c 修复问题,commit:
git add back_car-main/code/image_deal.cgit commit -m "fix(back): 修正过弯时连通域分裂导致目标丢失
加入连通域间距阈值,距离小于 5px 的合并为同一目标。解决在大弯道时车标和阴影被识别为独立目标的问题。
fixes #5"
git push -u origin fix/back-car-target-loss注意 fixes #5 —— 合并时会自动关闭 Issue #5。
第 3 步:发起 PR
GitHub 网页发 PR:
Title: fix(back): 修正过弯时连通域分裂导致目标丢失
Description:## 改动在 image_deal.c 的连通域后处理阶段加入间距阈值合并。
## 解决问题fixes #5
## 测试- ✅ 室内圆形测试场连续 10 圈无丢失- ✅ 模拟弯道阴影场景 50 次 0 丢失(之前 30%)
## 风险新增的合并逻辑会让"两辆很近的车"也被识别为一个,但本赛规则下不会出现两辆车同时在一辆后车前 1m 内。第 4 步:CI 跑通
✅ commitlint 通过✅ no-binary 通过✅ markdown-lint 通过✅ ci / lint 通过第 5 步:Code review + 合并
队友看完代码,点 Approve。你点 Squash and merge(小 PR 用 squash 让 main 历史干净)。
合并后:
- ✅ Issue #5 自动从 Open 变 Closed(因为 PR 描述里写了
fixes #5) - ✅ main 多了一个 squash commit
- ✅ 远程分支自动删除(设置过 Auto-delete head branches)
第 6 步:本地清理
git switch main && git pullgit branch -d fix/back-car-target-loss第 7 步:发 Release
修复积累到一定程度,准备发 v1.0.1:
git tag -a v1.0.1 -m "v1.0.1 - 后车过弯稳定性修复"git push origin v1.0.1如果配了 8.3.6 的 release.yml,接下来全自动:
- GitHub Actions 检测到 v1.0.1 tag
- 在 self-hosted runner 编译两个项目
- 自动创建 Release 页面,标题
v1.0.1 - 自动生成 release notes(包含上面的 PR)
- 附上
Front_Car.hex、Back_Car.hex等文件 - 标记为 Latest release
第 8 步:通知队友
只需要把 Release 页面 URL 发给队友:
https://github.com/forest-wang-sunshine/double_car/releases/tag/v1.0.1队友点进去能看到:完整改动列表、固件下载、关联的 Issue 和 PR。
GitHub 其他实用功能(速览)
Discussions
仓库 → Settings → Features → 勾 Discussions。
适合:开放性讨论、Q&A、想法征集(不像 Issue 那样必须有”要做的事”)。
格式比 Issue 更灵活,支持点赞、置顶、标记最佳回答。
Projects(任务面板)
仓库 → Projects → New project。
类似 Trello/Jira 的看板,把 Issues 和 PR 拖到不同列(Todo / In Progress / Done)。
适合:可视化追踪 milestone 进展、规划 sprint。
Wiki
仓库 → 顶部 Wiki 标签。
适合:长文档、用户手册、设计文档。
但实践中很多人推荐直接用 docs/ 目录 + markdown —— 因为:
- Wiki 是独立的 git repo,不能在主仓库 PR 流程里 review
docs/在主仓库里能跟代码一起版本化- 本项目的
docs/{requirements,plans}/已经是这种做法
Pages
仓库 → Settings → Pages。
把仓库里的 markdown/HTML 自动发布成网站,URL 类似 https://<用户名>.github.io/<仓库>/。
适合:项目主页、文档站点。配合 Jekyll/Hugo/MkDocs 等静态生成器更专业。
Insights
仓库顶部 Insights 标签:
- Pulse —— 最近一周活跃度
- Contributors —— 谁贡献了多少
- Traffic —— 谁访问过、从哪里来
- Commits —— 提交频率图
- Code frequency —— 增删行数趋势
- Network —— fork 关系图
- Forks —— 谁 fork 了你的项目
Security
仓库 → Security 标签:
- Dependabot —— 自动检测依赖漏洞并发 PR 更新(npm/pip 项目用,AURIX 项目不太适用)
- Code scanning —— 自动扫描代码安全问题
- Secret scanning —— 自动检测是否有人误把密钥提交进来
速查表
Issues 关键字(在 commit / PR / 评论里写)
close #N closes #N closed #N → 关闭 Issuefix #N fixes #N fixed #N → 关闭 Issueresolve #N resolves #N resolved #N → 关闭 Issue
#N → 引用 Issue(不关闭)@user → 提及某人@team-name → 提及团队常用 Markdown 在 Issue/PR 里的妙用
- [ ] 待办事项 1- [x] 已完成事项 2
```c// 代码块(带语法高亮)float kp = 1.5;```
> 引用别人的话
| 表头 | 表头 ||------|------|| 表格 | 内容 |
[链接文本](https://example.com)

<details><summary>折叠区域标题</summary>折叠的详细内容</details>Actions 常用 actions
- uses: actions/checkout@v4 # 拉代码- uses: actions/setup-node@v4 # Node.js 环境- uses: actions/setup-python@v5 # Python 环境- uses: actions/cache@v4 # 缓存- uses: actions/upload-artifact@v4 # 上传产物- uses: actions/download-artifact@v4 # 下载产物- uses: softprops/action-gh-release@v2 # 创建 Release- uses: peter-evans/create-pull-request@v6 # 创建 PR- uses: actions/labeler@v5 # 自动打标签Tag 与 Release 命令
git tag # 列出所有 taggit tag -l "v1.*" # 通配符过滤git tag -a v1.0.0 -m "说明" # 创建带注解的 taggit tag -a v1.0.0 <哈希> -m "..." # 给历史 commit 打 taggit tag -d v1.0.0 # 删本地 taggit push origin v1.0.0 # 推一个 taggit push origin --tags # 推所有 taggit push origin --delete v1.0.0 # 删远程 taggit show v1.0.0 # 看 tag 详情
# 用 gh CLIgh release create v1.0.0 --notes "..." file.hex # 创建 release 并附文件gh release list # 列表gh release view v1.0.0 # 查看gh release delete v1.0.0 # 删除分支保护规则配置位置
仓库 → Settings → Branches → Add branch protection rule仓库 → Settings → Rules → Rulesets → New ruleset (新版)文件位置约定
.github/├── CODEOWNERS 自动指定 reviewer├── ISSUE_TEMPLATE/ Issue 模板│ ├── bug_report.md│ └── feature_request.md├── PULL_REQUEST_TEMPLATE.md PR 模板├── workflows/ Actions 工作流│ ├── ci.yml│ ├── release.yml│ └── labeler.yml├── labeler.yml labeler action 的规则├── release.yml release notes 自动生成配置└── dependabot.yml Dependabot 配置一页纸总结
┌────────────────────────────────────────────────────────────────────┐│ GitHub 平台四大进阶功能 │├────────────────────────────────────────────────────────────────────┤│ ││ Issues 工单系统 ││ ────── PR 描述里写 "closes #N" 自动关单 ││ 用 Labels / Milestones / Assignees 组织 ││ .github/ISSUE_TEMPLATE/ 加模板 ││ ││ Actions 自动化工作流 ││ ────── .github/workflows/*.yml ││ on: 触发, jobs: 作业, steps: 步骤 ││ 用 secrets.* 引用密钥 ││ TASKING 编译要 self-hosted runner ││ ││ Releases 版本发布 ││ ────── 基于 Tag (vMAJOR.MINOR.PATCH) ││ git tag -a vX.Y.Z -m "..." && git push --tags ││ 配合 release.yml 工作流自动构建+发布 ││ ││ Branch 分支保护 ││ Protection Settings → Branches → Add rule ││ ────── 必勾:Require PR / Require status checks / ││ Do not allow bypassing ││ 必关:Allow force pushes / Allow deletions ││ │├────────────────────────────────────────────────────────────────────┤│ ││ 完整生命周期: ││ ││ 开 Issue → 创建分支 → 写代码 → PR → CI 通过 → review → ││ 合并(自动 close Issue)→ 累积改动 → 打 Tag → ││ Actions 自动构建 → 自动创建 Release → 通知用户 ││ │└────────────────────────────────────────────────────────────────────┘
semver: v MAJOR . MINOR . PATCH ↑ ↑ ↑ 不兼容 新功能 修 bug本教程在 2026-05-04 整理,基于 double_car 项目的协作场景。可作为团队 GitHub 工作流的参考标准。
部分信息可能已经过时














