第 06 章

开源贡献

fork 模型、upstream 同步——给真正的开源项目提交代码

你的第一个 upstream PR,就在本章

想贡献却卡住

你用着一个开源库,发现 bug,想帮忙改——然后呢

没权限直接改

你想改别人的仓库,但没有推送权限。clone 下来改完,怎么把改动送回去?

fork 是什么

听说要「先 fork」,但 fork 之后呢?自己的 fork 和原仓库什么关系?origin 和 upstream 又怎么区分?

不知从何下手

大项目几百个 issue,哪个适合新人?怕改得不好被拒,干脆不贡献了。

本章带你走完一次真实的开源贡献:从挑选合适的 issue,到 fork、改代码、同步上游、提交 upstream PR、回应 review。
学完这章,你就有能力给任何开源项目贡献代码了。

开始之前

适合谁

  • 会 PR,但只在自己的项目里做过
  • 想给开源项目贡献,却没迈出第一步
  • 被 fork / upstream / origin 绕晕过

你将学会

  • 理解 fork 模型和两份仓库的关系
  • 同步 upstream 保持 fork 最新
  • 读懂 CONTRIBUTING 和行为准则
  • 用 good first issue 找到合适的入门任务
  • 提交一个规范的 upstream PR

本章暂不覆盖

  • 开源协议选择(法律范畴)
  • 维护自己的开源项目(进阶)
  • GitHub Sponsors 赞助

fork 是什么

把别人的仓库「复印」一份到你自己的账号下

图:fork 模型与两个 remote
关键认知:fork 后你有两份仓库。一份是你的 fork(origin,你能 push),一份是原作者的(upstream,你只能 fetch)。你的改动推到 origin,再从 origin 向 upstream 提 PR。

怎么 fork

在原仓库页面点一个按钮就行

操作步骤

  1. 打开你想贡献的仓库页面(如 github.com/原作者/项目)
  2. 右上角点 Fork 按钮
  3. 选择 fork 到你的账号下
  4. 几秒后,你的账号下出现 github.com/你/项目

fork 之后

这个 fork 是你自己的副本,你可以随便改、随便推,不会影响原仓库。
原仓库页顶会显示「forked from 原作者/项目」。

fork 是服务端操作,在你的 GitHub 账号里复制一份。接下来要把这份 fork clone 到本地才能改代码。

克隆你的 fork

注意:clone 的是你自己的 fork,不是原仓库

# clone 你的 fork(origin 自动指向它)
$ git clone https://github.com/你/项目.git
$ cd 项目

# 查看当前 remote
$ git remote -v
origin  https://github.com/你/项目.git (fetch)
origin  https://github.com/你/项目.git (push)
常见错误:直接 clone 了原仓库。那样你没有推送权限,改完没法 push。
一定要 clone 你自己账号下的那份 fork。地址里应该是你的用户名。

关联上游

手动添加原仓库为 upstream,方便后续同步

# 添加原作者仓库为 upstream(名字可自定义,约定叫 upstream)
$ git remote add upstream https://github.com/原作者/项目.git

# 现在有两个 remote
$ git remote -v
origin    https://github.com/你/项目.git (fetch/push)
upstream  https://github.com/原作者/项目.git (fetch)

为什么需要 upstream

原作者会持续更新仓库。你的 fork 不会自动同步。要定期从 upstream 拉更新,否则你的 fork 越来越旧,提 PR 时容易冲突。

注意:upstream 只有 fetch 权限(只读),你无法 push 到 upstream。

同步上游

把原作者的最新改动拉到你的本地,再推到你的 fork

# 1. 拉取 upstream 的最新内容(只下载,不合并)
$ git fetch upstream

# 2. 切到 main 并确保是最新
$ git checkout main
$ git merge upstream/main

# 3. 把同步后的 main 推到你的 fork(origin)
$ git push origin main
这三步要定期做。尤其在准备提 PR 之前——确保你的 fork 基于最新的上游代码,减少冲突概率。
GitHub 网页也有一键同步按钮:你的 fork 页面 → Sync fork。

贡献全流程

从开分支到提 upstream PR 的完整节奏

图:开源贡献的完整步骤

动手前

改代码之前,先做这两件事

同步上游

确保你的 fork 基于最新代码:

$ git checkout main
$ git fetch upstream
$ git merge upstream/main
$ git push origin main

开专属分支

从最新 main 开分支,名字说清改什么:

$ git checkout -b fix/typo-in-readme

不要在 main 上直接改。每个贡献一条独立分支。

CONTRIBUTING

贡献指南——告诉你这个项目要怎么提交

在哪看

  • 仓库根目录的 CONTRIBUTING.md
  • 或仓库页 Contributing 链接(部分项目)

里面通常写明

  • 如何搭建开发环境
  • 代码风格规范
  • 提交 PR 前要跑的测试
  • commit 消息格式
  • 分支命名约定
贡献前必读 CONTRIBUTING。不读就提交,大概率因为不符合规范被拒。维护者花时间写这份文档,就是为了减少无效沟通。

行为准则

Code of Conduct——开源社区的礼仪公约

它规范什么

  • 如何友善地交流
  • 哪些行为不被容忍(人身攻击、歧视等)
  • 违反了怎么举报

对你意味着

在 issue、PR、讨论里保持尊重和专业。技术分歧可以争,但不攻击人。这是参与开源的基本前提。

贡献即同意。提交 PR 通常视为你接受了项目的行为准则。常见模板有 Contributor Covenant,大多数项目直接采用。

找入门任务

good first issue——专为新人准备的简单任务

怎么找

仓库 → Issues → 搜索框输入:

label:"good first issue"

或 GitHub 全局搜索:github.com/issues?q=label:good-first-issue

其他友好标签

  • help wanted:维护者欢迎帮忙
  • documentation:文档类,门槛低
  • beginner-friendly:类似 good first issue
good first issue 是为你准备的。维护者已经判定这些任务范围小、说明清楚、适合新人。不要怕,挑一个开始。

先沟通再动手

大改动前先在 issue 里说一声——避免白干

小改动

修 typo、改文档、明显的 bug——直接做,提 PR 即可。不用预先沟通。

大改动

新功能、重构——先在 issue 里描述方案,等维护者认可再写代码。
否则可能花一周写完被拒绝「我们不想要这个功能」。

这是开源的基本礼仪:维护者的时间宝贵,你的时间也宝贵。先对齐方向,再投入实现,双方都省事。

提 upstream PR

push 到你的 fork 后,向原仓库发起 PR

# push 你的 feature 分支到 fork(origin)
$ git push -u origin fix/typo-in-readme

关键:base 和 head

  • base:选 原作者/项目/main(合并目标)
  • head:选 你/项目/fix/typo-in-readme(你的改动)

跨仓库的 PR,GitHub 会自动识别 fork 关系。

入口:push 后,GitHub 会在你的 fork 页面提示「Compare & pull request」。点进去,确认 base 是原仓库、写好描述,提交即可。

PR 描述要点

开源 PR 的描述要更完整——维护者不认识你

## 改动说明
修复 README 安装步骤中的 typo,把 `npm intsall` 改为 `npm install`。

## 关联 issue
Closes #45

## 改动类型
- [x] 文档修复

## 检查清单
- [x] 已阅读 CONTRIBUTING.md
- [x] 改动只涉及文档,不影响代码
- [x] 本地已预览渲染效果
开源 PR 描述要回答三个问题:改了什么、为什么改、怎么验证。
维护者是陌生人,给他们足够的上下文,你的 PR 才会被快速审阅。

回应 review

维护者要求修改是常态——不是否定

正确心态

  • request changes 是协作的一部分,不是批评
  • 维护者比你了解项目,意见通常有道理
  • 有不同想法可以礼貌讨论

怎么响应

  • 在同一分支上继续 commit 修改
  • push 后 PR 自动更新
  • 每条意见回复一下:「已改」「这个我有不同看法,因为...」
  • 别 squash 掉讨论痕迹,保留对话历史
不要因为被要求修改就放弃。很多新人的第一个 PR 卡在 review 环节就关掉了。坚持改完,合并的那一刻你会很有成就感。

合并之后

你的贡献正式成为开源项目的一部分

会发生什么

  • 你的头像出现在仓库的 Contributors 列表
  • 你的 GitHub 头像绿了对应日期(贡献图)
  • 这是你简历上能写的真实开源经历

清理工作

  • 删除本地的 feature 分支
  • 同步 upstream(现在含你的改动)
  • 你的 fork 上保留分支即可,GitHub 会提示删
恭喜!你已经是一个开源贡献者了。从 typo 到功能,每个贡献都算数。坚持下去,你的 Contributors 列表会越来越长。

从哪开始

适合第一次贡献的途径

你正在用的工具

你最熟悉的库/工具是最好的起点。你了解它的用法,容易发现问题。边用边贡献,动机最强。

聚合网站

  • goodfirstissue.dev:汇集 good first issue
  • up-for-grabs.net:友好开源项目列表
  • firsttimersonly.com:新人指南

文档类起步

修 typo、补说明、翻译文档——门槛最低、最容易被合并。适合建立第一次信心。

动手试一试

完成你的第一次 fork-PR 流程

你的任务

任务:fork 一个开源仓库,走完整的贡献流程(可以不合并,重点是练手)。

要求:

  1. fork octocat/Spoon-Knife(GitHub 官方练手仓库)
  2. clone 你的 fork 到本地
  3. 添加 upstream remote
  4. 开 feature 分支,改一个文件(如 README 加一行)
  5. push 到 origin,向 upstream 提 PR
  6. 体验完整流程,之后可自行关闭 PR

提示

  1. Spoon-Knife 是专为练习 fork/PR 设计的仓库
  2. 提 PR 时确认 base 是 octocat/Spoon-Knife
第 06 章

小结

你已经具备给任何开源项目贡献代码的能力

本章要点

  • fork = 复印别人的仓库到自己账号,你有完全控制权
  • 两个 remote:origin(你的 fork,可推)、upstream(原仓库,只读)
  • 定期从 upstream 同步,保持 fork 最新
  • 贡献前读 CONTRIBUTING,大改动先沟通
  • good first issue 是新人的最佳入口
下一步:第 07 章 GitHub Actions —— 进入自动化篇,让代码在 push 后自动测试、构建、部署。