仓库管理的目标不是把 Settings 页面全部点一遍,而是让“谁能改、改什么、怎样合并、怎样发布、出了问题找谁”变得可解释、可审计、可恢复。
本篇讲 Repository 的文件与元数据、权限、Issue 规划、默认分支、Branch Protection、Rulesets、Required Checks、Release、Archive、Transfer 与安全维护。GitHub Actions 只在“哪些检查必须通过、如何接入规则”这一边界出现,不展开 workflow YAML、Runner、Matrix、Cache 或凭据注入;这些内容留给本专题 04–06。
1. 仓库的两层:代码契约与平台治理#
一个 GitHub 仓库同时有两种状态:
- 仓库内的契约(repository-as-code):README、LICENSE、CHANGELOG、贡献指南、Issue/PR 模板、CODEOWNERS、工作流与配置文件,能随 Git 历史审查、复制和回滚。
- GitHub 平台的治理状态(repository settings):可见性、角色、默认分支、分支规则、合并按钮、Issue/Projects 开关、Actions 权限与安全功能,通常在 Settings 或 API 中维护。
两者要相互印证。README 写“需要 Pull Request”并不等于平台已经禁止直接推送;workflow 文件存在也不等于它的检查已成为 Required Check;LICENSE 文件存在也不等于仓库的 License 元数据已被识别。
flowchart LR
A[仓库文件与 Git 历史] --> B[平台元数据]
B --> C[权限与规则]
A --> D[Issue / PR / Release]
C --> E[Required Checks]
D --> E
E --> F[可审计的合并与发布]1.1 基础文件的职责
| 文件或设置 | 解决的问题 | 维护要点 |
|---|---|---|
README.md |
项目是什么、如何安装和使用 | 给首次访问者一条可运行路径;不要把全部设计史塞进 README |
README_EN.md 或其他语言 README |
面向不同读者的入口 | 两种语言至少同步安装、兼容性和限制;链接到同一份变更记录 |
LICENSE |
使用、修改、再分发的法律边界 | 使用 SPDX 名称;许可证文本要与仓库元数据一致 |
CHANGELOG.md |
人类可读的行为变化 | 按版本记录 breaking change、修复、迁移和已知限制 |
CONTRIBUTING.md |
外部贡献者怎样开始 | 写清本地检查、分支、PR、Review 和行为规范 |
SECURITY.md |
私下报告漏洞的路径 | 写明支持版本、报告渠道和不要公开披露的内容 |
CODEOWNERS |
哪些路径需要谁 Review | 规则应覆盖关键代码、工作流和安全配置;路径变更要随代码审查 |
.github/ISSUE_TEMPLATE/ |
让 Issue 带有可行动的信息 | Bug、Feature、Security 等类型分别要求复现、目标和影响 |
.github/PULL_REQUEST_TEMPLATE.md |
让 PR 自带检查清单 | 说明变更、测试、风险、文档和关联 Issue |
.github/workflows/ |
把质量检查自动执行 | 本篇只关心它提供的检查是否稳定并接入合并规则 |
README 负责“如何使用”,CONTRIBUTING 负责“如何改变”,SECURITY 负责“如何私下报告风险”,CODEOWNERS 负责“谁必须看”。把它们混在一个 README 里,会让普通用户、贡献者和安全报告人都找不到最短路径。
1.2 仓库元数据不只是装饰
建议至少维护以下元数据:
- 一句话 description:说明项目对象,不写成营销口号。
- Topics:使用稳定的技术名、语言名和生态名,帮助检索;不要把每个版本号都做成 Topic。
- License:选择与
LICENSE内容相符的许可证。 - Default branch:通常是
main,但要与文档、CI 触发条件和发布流程一致。
只读查看可使用 GitHub CLI:
gh repo view OWNER/REPO \
--json nameWithOwner,visibility,defaultBranchRef,isArchived,licenseInfo,url官方说明:About repositories、About repository topics、GitHub CLI gh repo view。
1.3 示例:如何记录一个仓库治理快照
以下是匿名化的教学情境,不是对某个实际仓库当前状态的核验:假设一个公开主题项目使用 main 作为默认分支,维护中文、英文 README 与 CHANGELOG,采用 BSD 2-Clause 许可证,发布过 v0.1.0 与 v0.2.0,并已有 .github/workflows/nix.yml。这些文件与版本身份需要分别核对,不能根据 README 推断平台设置。
治理审计应把以下对象记录在同一个核验日期下:
- 用
gh repo view OWNER/REPO --json visibility,defaultBranchRef,isArchived,licenseInfo查看可见性、默认分支、归档状态与许可证元数据。 - 检查 LICENSE、两种语言的 README、CHANGELOG 与 Release notes 是否一致。
- 用
gh release list --repo OWNER/REPO查看版本发布记录;“Latest” 只描述查询时的平台标记。 - 查找
CONTRIBUTING.md、SECURITY.md、CODEOWNERS和 Issue/PR 模板,明确已存在和待补充的契约。 - 用
gh ruleset list --repo OWNER/REPO和保护 API 核对合并规则。保护 API 的 404 可能受配置、权限或目标路径影响,应结合其他证据解释。
一个“有 CI、缺贡献文档、未查到保护规则”的示例只能说明治理需要补齐;不能把它当成未来状态承诺,也不能由此判断是否有贡献者活动。
2. 可见性、权限与角色#
2.1 先选边界,再授予权限
仓库的可见性回答“谁能看见”,角色回答“看见以后能做什么”:
| 概念 | 稳定语义 | 常见误区 |
|---|---|---|
| Public | 任何人可以访问公开内容;写入仍需要权限 | 公开不等于任何人都能 push |
| Private | 只有明确获授权的用户、团队或组织成员可访问 | private fork、Actions 日志和依赖能力可能受平台规则影响 |
| Internal | 适用于组织/企业内部可见的场景 | 个人仓库未必提供此语义,不能当作 Public 与 Private 的通用中间态 |
| Fork | 共享上游关系的派生仓库 | 改可见性或转移仓库可能影响 fork network 和权限 |
GitHub 的套餐、仓库所有者类型和组织策略会影响某项能力是否可用。不要把某个 Settings 页面当前显示的按钮、数量或免费额度写成永久规则;遇到差异时以当前 GitHub plans 和 repository visibility 文档 为准。
2.2 角色的最小权限原则
不同仓库类型的 UI 名称可能略有差异,但治理上可以按以下层级思考:
- Read:查看代码、Issue、PR 和公开元数据;适合观察者和只读集成。
- Triage:处理 Issue、PR 分类、标签和项目队列,不直接改变代码。
- Write:推送允许的分支、创建 PR、运行常规协作流程。
- Maintain:维护仓库配置和日常管理,但通常不应承担全部敏感或破坏性管理权。
- Admin:修改仓库治理、安全与权限,并执行高影响操作;只给真正的仓库管理员。
组织仓库优先授予团队而不是逐个用户;关键路径使用 CODEOWNERS 明确 Review 责任;临时协作者设置到期复核。不要为了让某人“能关 Issue”就直接给 Write,更不要用 Admin 解决一个局部权限问题。参考 Repository roles for an organization。
2.3 修改可见性前的检查
修改 Public/Private 不是普通的标签切换,应先检查:
- 是否包含历史中的凭据、个人信息、内部链接或不应公开的构建日志。
- 公开 fork、clone、缓存和 Release 是否会改变暴露面。
- 依赖的 Actions、Packages、Pages、Webhook 和部署环境是否接受新的可见性。
- 是否已告知协作者,并安排可逆的观察窗口。
- 是否需要先迁移秘密、重写历史或轮换已暴露凭据。
CLI 可以表达意图,但不会替代风险评估:
gh repo edit OWNER/REPO \
--visibility private \
--accept-visibility-change-consequences只有确认后果并拥有足够权限时才执行。官方 CLI 说明:gh repo edit。
3. Issues、Labels、Milestones 与 Projects#
3.1 Issue 是可追踪的决策对象
一个好 Issue 至少有:问题或目标、影响范围、复现/验收条件、相关版本、当前阻塞因素。讨论可以很开放,但最终要沉淀为可关闭、可引用和可复盘的记录。
建议把标签分成少量稳定维度:
| 维度 | 示例 | 作用 |
|---|---|---|
| 类型 | bug、enhancement、documentation、security |
说明问题是什么 |
| 状态 | triage、blocked、needs-info |
说明现在卡在哪里 |
| 范围 | nix、theme、ci、docs |
说明由谁或哪部分处理 |
| 贡献门槛 | good first issue、help wanted |
帮助新贡献者筛选任务 |
标签名应可组合,但不要为每个组合创建新标签;“类型 + 范围 + 状态”通常已经足够。Security Issue 不应把敏感细节写进公共 Issue,应转到 SECURITY.md 指定的私下渠道。
Issue 模板应要求信息,而不是增加表单负担:Bug 模板收集环境、复现步骤、预期/实际结果和日志脱敏;Feature 模板收集动机、替代方案和验收条件;问题报告模板不应要求用户粘贴凭据。模板的官方入口是 About issue and pull request templates。
常用 CLI 查询与创建:
gh issue list --repo OWNER/REPO --state open --label bug
gh issue view 123 --repo OWNER/REPO
gh issue create --repo OWNER/REPO --title "简短标题" --body-file issue.md3.2 Milestone 连接 Issue 与版本目标
Milestone 适合表达一个有边界的交付目标,例如 v0.3.0、Nix CI hardening 或 Documentation refresh:
- 给出目标、截止日期或发布窗口,但把日期视为计划,不是假定的承诺。
- 把必须完成的 Issue 和 PR 关联进去。
- 用完成比例发现范围膨胀,而不是用它代替详细项目计划。
- 发布完成后关闭或归档对应目标,保留未完成项的去向。
GitHub 会在 Milestone 页面汇总开放/关闭的 Issue、PR 和完成比例;具体上限和 UI 可能变化,参见 About milestones。
3.3 Projects 是跨 Issue/PR 的视图层
Projects 适合做队列、看板、表格或路线图:
- Issue/PR 是工作的事实记录,Project 是整理和查看它们的视图。
- 用自定义字段表达优先级、状态、负责人、目标版本等;字段要少而稳定。
- 一个工作项可以出现在多个视图,不要复制出多个彼此冲突的 Issue。
- 定期关闭失效项,避免看板变成“所有想法的墓地”。
个人仓库、组织仓库与套餐可能提供不同 Projects 能力;以 About Projects 和当前界面为准。
4. 默认分支、保护规则与 Required Checks#
4.1 默认分支是协作入口
默认分支决定新 PR 的默认目标、仓库首页展示内容、部分 Actions 触发语义和 Release 的默认基线。更换它之前应:
- 确认目标分支已经包含要展示的代码和文档。
- 检查 README、贡献指南、工作流、脚本和外部链接中的旧分支名。
- 通知协作者更新本地 upstream 与 PR 目标。
- 迁移保护规则、Rulesets、CODEOWNERS 相关路径和发布自动化。
- 观察旧分支是否仍有开放 PR,再决定是否删除。
gh repo view OWNER/REPO --json defaultBranchRef
gh repo edit OWNER/REPO --default-branch maingh repo edit 的写操作应在审查后执行;若只是检查,优先使用第一条只读命令。参考 Changing the default branch。
4.2 Branch Protection 与 Rulesets 的选择
两者都在保护分支或标签,但管理模型不同:
| 机制 | 适用理解 | 需要注意 |
|---|---|---|
| Branch protection rule | 对匹配分支设置一组常见保护项 | 规则直观,适合简单仓库;匹配与叠加行为要按当前文档确认 |
| Ruleset | 命名、可查看、可设置 enforcement 状态的一组规则 | 可以针对分支或标签,多个 Rulesets 可同时生效,适合逐步推广与审计 |
两者不是“打开一个就完全替代另一个”。适用规则会共同影响合并和推送;管理员应避免重复、互相矛盾的规则。Ruleset 可以先以 Evaluate 等非强制状态观察命中结果,再切到 Active;具体可用状态和规则随产品演进,参见 About rulesets 与 Available rules for rulesets。
4.3 一套可解释的 main 基线
对拥有持续维护的仓库,通常从以下保护项中按风险选择:
- 要求通过 Pull Request,禁止未经审查的直接合并。
- 要求至少一名合适的 Review;关键路径由 CODEOWNERS 指定审查者。
- 新提交后使过时批准失效,避免“审查的是旧代码”。
- 要求对话解决,确保 Review 中的阻塞意见有结论。
- 要求 Required Checks 成功、跳过或中立后才允许合并;检查名称要稳定。
- 需要分支与 base 更新后再合并时启用 strict checks;低频仓库可评估额外构建成本。
- 视项目需要要求线性历史、签名提交、成功部署、禁止 force push 与删除。
- 设定清晰的 bypass 角色,并把绕过规则的使用纳入审计。
规则不是越多越安全。每一项都应回答“要阻止的风险是什么、谁可以例外、失败后如何恢复”。
4.4 Required Checks 的真正边界
Required Check 是合并门槛,不是 CI 设计本身。配置前先确认:
- 该检查在目标 PR 类型上一定会运行,不能因为路径过滤、权限或事件差异而无故缺失。
- 检查名稳定且能唯一对应预期的工作;矩阵检查尤其要避免名字碰撞。
- 检查来源可信,必要时限制到预期的 GitHub App 或服务。
skipped、neutral、失败与取消的语义符合项目风险;不要把“没有运行”误当“已经测试”。- strict 与 loose 的选择符合仓库规模:strict 更接近合并时的最新 base,代价是可能重复构建。
- 分支规则只要求已有且稳定的检查;先观察一段时间,再把它设为 Required。
本篇不展开 Actions workflow 语法。只需要把 Actions 视为产生 Check 的执行方,后续在 04–06 中学习如何设计、配置和保护它。官方语义见 About protected branches,其中包含 Required Status Checks 的 strict/loose 取舍。
若示例项目的 .github/workflows/nix.yml 与 CHANGELOG 表明已经有 Nix CI,但“有工作流”与“main 受 Required Checks 保护”是两件事。接入规则前应在真实 PR 中确认检查名称、触发条件和失败恢复路径。
只读审计可以使用:
gh ruleset list --repo OWNER/REPO
gh ruleset check main --repo OWNER/REPO
gh api repos/OWNER/REPO/branches/main/protection末条在未配置保护时可能返回 404;应结合仓库设置、Rulesets 列表和权限上下文解释,不能单独把网络错误当成配置结论。参考 gh ruleset 与 gh api。
5. Tags、Releases、Archive 与 Transfer#
5.1 Tag 与 Release 是两个层次
- Git tag 指向某个提交,是版本身份的一部分;发布前应确认它指向可复现、已审查的提交。
- GitHub Release 是围绕 tag 的分发页面,可附带变更说明、资产、安装提示和预发布/草稿状态。
- CHANGELOG 是仓库内的长期历史;Release notes 是面向该版本用户的交付说明。两者可以互相链接,但不应只存在一份。
推荐的发布顺序:
- 先合并代码、文档和
CHANGELOG,明确兼容性、迁移与已知限制。 - 创建并审查版本 tag,检查 tag 对应的 commit 和源码归档。
- 创建 Release,写清用户能感知的变化、验证方法和不支持范围。
- 如果有构建资产,记录来源、校验方式和平台差异;不要把未验证的构建产物标成稳定版。
- 发布后验证安装/升级路径,并把问题回链到 Issue 或下一个 Milestone。
CLI 查询示例:
gh release list --repo OWNER/REPO
gh release view v0.2.0 --repo OWNER/REPO参考 About releases、Managing releases 与 gh release。
示例版本规划可以让 v0.1.0 提供初始主题与安装路径,让 v0.2.0 增加 compositor 原生模糊变体、Home Manager 模块、输出契约检查与 Nix CI。这里的版本安排仅用于说明发布记录的分工。Release 页面与仓库内 CHANGELOG.md 的版本号应保持可互相验证。
5.2 Archive 与 Transfer 是高影响操作
Archive 表示项目不再积极维护:内容通常保留为只读参考,Issue/PR 与部分协作入口会受到限制。归档前应发布维护状态、替代项目和安全报告路径;归档不等于删除,也不能替代备份。
Transfer 会改变所有者或仓库命名空间,可能影响:
- clone URL、远程配置和外部链接;
- issue、PR、项目、Actions、Secrets、Webhooks、Packages 与部署;
- fork network、团队权限和 CODEOWNERS;
- 许可证、品牌、维护责任与安全报告渠道。
转移前先列出依赖方、通知协作者、确认目标命名空间和管理员,转移后再验证 redirect、默认分支、规则、Release 与 CI。参考 Transferring a repository 与 Archiving a GitHub repository。
6. 仓库安全基线与维护清单#
6.1 最小安全基线
对公开仓库,最小基线应包含:
- 不提交 token、密码、私钥、
.env或含凭据的构建日志;发现泄露时先撤销/轮换,再处理历史。 - 用
SECURITY.md指定私下报告渠道、支持版本和响应边界;公共 Issue 不承载漏洞细节。 - 对关键路径使用 CODEOWNERS;工作流、发布配置和依赖更新不应无人 Review。
- 启用可用的 secret scanning 与 push protection,并理解其覆盖范围、误报和绕过流程。
- 评估 Dependabot alerts、Dependabot security updates、dependency review 与 code scanning;能力取决于仓库类型、组织策略和套餐。
- Actions 只授予所需权限;第三方 Action 固定到经过审查的版本或提交,并定期更新。
- 用 Branch Protection/Rulesets 把关键检查、Review 和禁止破坏性推送落实为平台规则。
GitHub 的安全功能会持续变化,不要把某一套餐的按钮当成所有仓库都拥有的能力。官方入口:Quickstart for securing your repository、Secret scanning、Adding a security policy 与 About code owners。
6.2 可执行的维护清单
| 时机 | 检查 | 证据 |
|---|---|---|
| 每次变更 | PR 描述、关联 Issue、Required Checks、Review 责任 | PR、Check run、Review 记录 |
| 每周或每次集中维护 | 清理无效 Issue,补充标签,更新 Milestone/Project 状态 | Issue 历史和项目视图 |
| 每次发布 | 版本号、CHANGELOG、tag、Release notes、安装验证 | tag、Release、验证命令/日志 |
| 依赖更新 | 依赖告警、变更范围、兼容性与回滚方案 | Dependabot/PR/Release 记录 |
| 每月或每季度 | 权限、团队成员、bypass、Secrets、Webhook 和规则 | Settings 审计、组织日志、规则快照 |
| 发生安全事件后 | 撤销凭据、判断历史暴露、通知受影响者、复盘防护缺口 | 私下报告记录和修复 PR |
6.3 示例项目的治理优先级
对上述教学情境,可以从治理角度排序:
- 添加
CONTRIBUTING.md,写明本地 Nix 检查、PR 证据、文档同步和兼容性声明。 - 添加
SECURITY.md,定义安全报告渠道,并提醒不要在公共 Issue 粘贴凭据或漏洞细节。 - 添加最小 Bug/Feature/PR 模板,让 Issue 和贡献请求可复现、可验收。
- 若维护者希望关键路径强制 Review,再添加 CODEOWNERS,并检查文件路径与权限。
- 观察
.github/workflows/nix.yml产生的实际 check 名称与失败率,再为main设计 Ruleset/Branch Protection 与 Required Checks。 - 规则稳定后,把规则、发布流程和安全检查写进文档,形成“仓库文件 + 平台设置 + 验证命令”的闭环。
这份排序避免先设置一个没人理解的 Required Check,也避免把社区文件当成装饰性模板;每一项都应服务于真实贡献和发布流程。
7. 官方资料与延伸阅读#
- GitHub Docs
- GitHub CLI Manual
- About repositories
- Repository roles
- About issues
- About protected branches
- About rulesets
- About releases
- Quickstart for securing a repository
- GitHub CLI
gh repo edit - GitHub CLI
gh ruleset - GitHub CLI
gh release
GitHub 的 UI、套餐、权限和产品限制会变化;遇到文档与当前界面不一致时,以当前官方文档和仓库 Settings 的实际结果为准,并在项目维护记录中更新核验日期。
参考与延伸
- About repositories ↗
- About repository topics ↗
- GitHub CLI `gh repo view ↗
- GitHub plans ↗
- repository visibility 文档 ↗
- Repository roles for an organization ↗
- gh repo edit ↗
- About issue and pull request templates ↗
- About milestones ↗
- About Projects ↗
- Changing the default branch ↗
- About rulesets ↗
- Available rules for rulesets ↗
- About protected branches ↗
- gh ruleset ↗
- gh api ↗
- About releases ↗
- Managing releases ↗
- gh release ↗
- Transferring a repository ↗
- Archiving a GitHub repository ↗
- Quickstart for securing your repository ↗
- Secret scanning ↗
- Adding a security policy ↗
- About code owners ↗
- GitHub Docs ↗
- GitHub CLI Manual ↗
- About issues ↗
根据技术笔记重新整理,示例使用通用名称。