GitHub 到底在 Git 之外做了什么?从 Issue、Fork 到 Pull Request
前言
假设你发现一个开源项目里有个小 Bug,想顺手修掉。
从 Git 的角度,你知道怎么操作:
1 | git clone git@github.com:owner/repo.git |
但问题来了:
- 你有没有权限 push 到这个仓库?
- 你应该 push 到哪个分支?
- 谁来确认你的改动是对的?
- 测试有没有跑过?
- 如果主分支不能被随便改,改动怎么进去?
这些问题,Git 命令本身不回答。
Git 解决的是版本怎么记录。GitHub 解决的是多人怎么围绕这些版本协作。
这篇文章不是 Git 命令教程。它要讲的是:GitHub 这类代码托管平台,在 Git 本身的版本控制能力之外,为团队协作和开源贡献增加了什么。
Git 本身已经提供了什么
在讲 GitHub 之前,先快速回顾一下 Git 自己提供了哪些能力。
Git 是一个分布式版本控制工具。它的核心能力其实就这几样:
- commit:记录一次改动。每次 commit 有一个唯一的哈希值,记录了改了什么文件、谁改的、什么时候改的、改的原因是什么。
- branch:从某个 commit 拉出一条独立的开发线。不同分支上的改动互不影响。
- merge / rebase:把两条分支上的改动整合到一起。
- remote:连接一个远程仓库。
origin就是最常见的远程仓库名。 - push / fetch / pull:本地和远程之间同步代码。
push是把本地 commit 推到远程,fetch是从远程拉取新的 commit,pull是fetch加merge。
画个图大概长这样:
1 | 本地仓库 |
到这里,Git 已经可以让多人共享代码了。你把仓库推到远程,别人 clone 下来,各改各的分支,再 push 回去。
但是 Git 本身不关心这些事情:
- 谁有资格把代码合并进主分支?
- 这个 commit 是为了解决哪个 Bug?
- 测试跑过了没有?
- 有没有人看过这段代码?
- 主分支能不能被直接 force push?
这些判断,Git 不做。它只负责忠实地记录版本。
GitHub 这类平台补上的是什么
GitHub(以及 GitLab、Gitea、Forgejo 这些平台)做的事情,是在 Git 之上加了一层协作对象和协作规则。
Git 里有 commit。但 Git 不知道这个 commit 是为了解决哪个 Issue,也不知道它能不能合进 main。这些判断,是代码托管平台来组织的。
平台层补上的东西大致有这些:
- Repository:代码和项目协作的入口
- Issue:问题、需求、任务和讨论
- Pull Request:改动申请和代码审查入口
- Fork:没有写权限时的贡献副本
- Review:代码审查
- CI / Status Checks:自动化验证结果
- Branch Protection:保护主分支的规则
- Permissions:决定谁能读、写、管理仓库
用一张图来对比:
1 | Git 能力: |
这两层不是替代关系。GitHub 没有把 Git 改成另一个东西。Git 还是那个 Git,commit 还是那个 commit。平台只是在上面加了一套机制,让多人围绕同一份代码协作时,有地方讨论、有流程可走、有规则可守。
下面逐个来看。
Issue:先把问题说清楚
很多人以为 Issue 就是用来报 Bug 的。其实不是。
Issue 可以是:
- 一个 Bug 报告
- 一个新功能需求
- 一个任务拆分
- 一个设计讨论
- 一个文档问题
- 一个版本计划中的条目
Issue 的本质是一个可追踪的讨论对象。它有标题、描述、标签、指派人、状态(开着还是关了)、评论区。你可以把它理解成一个”工单”或者”话题”。
为什么需要这个东西?
假设你发现项目启动时报错。如果你直接发一个 PR 改了代码,维护者可能会想:这个问题真的存在吗?是不是你环境配错了?这个改动和已有设计有没有冲突?有没有其他人已经在修了?
先开一个 Issue,把情况说清楚,可以让所有人先对问题达成共识。
一个写得好的 Issue 大概长这样:
1 | Issue |
Issue 的作用不是”写给机器看”,而是让人先对问题达成共识。
当然,不是所有改动都必须先开 Issue。小的文档修正、明显的 typo、项目规则允许的情况下,直接提 PR 也行。但比较大的改动,最好先 Issue 讨论,避免做无用功。
另外要注意,Issue 不是 Git 本身的概念。git log 里看不到 Issue。Issue 是平台提供的,它和 commit 之间的关联,也是平台帮你做的(比如在 PR 描述里写 fixes #123,合并时会自动关闭对应的 Issue)。
GitLab 里类似的功能叫 Issue,Gitea 和 Forgejo 也叫 Issue。概念是一样的。
Branch:不要直接在主线上改
这一节简单,但很重要。
在大多数项目里,主分支(通常是 main 或 master)代表的是稳定状态。它是可以部署的、可以发布的、团队共同依赖的代码基线。
如果你直接在主分支上改代码,改坏了就会影响所有人。所以通常的做法是:为每个改动创建一个单独的分支。
1 | main |
创建分支的命令很简单:
1 | git checkout -b fix-login-error |
分支不是为了炫技。它只是让你的改动先待在一个安全的地方,不要直接污染主线。
分支名最好能看出意图。fix-login-error 比 my-branch 好得多。有些团队有命名规范,比如 feature/xxx、fix/xxx、docs/xxx。
注意一个细节:main 和 master 指的是同一种东西——项目的默认分支。不同项目叫法不同。Git 早期默认用 master,后来 GitHub 把默认值改成了 main。你两个都会见到,不要以为是不同的概念。
Pull Request:不是 Git 命令,而是一张改动申请单
这是全文最核心的一节。
Pull Request(PR)不是 Git 本身的命令。 你在 git --help 里找不到它。PR 是 GitHub 这个平台发明的协作对象。(GitLab 里类似的东西叫 Merge Request,简称 MR,本质是一样的。)
PR 做的事情是:把你的一组 commit 打包成一个”改动申请”,提交给目标分支,等待审查和合并。
一个 PR 里包含这些东西:
1 | 你的分支:fix-login-error |
这里有两个重要的术语:
- base branch:要合入的目标分支,通常是
main。 - head branch:包含你改动的来源分支,就是你创建的那个分支。
PR 的目的不是单纯”上传代码”。如果只是把代码推到远程,git push 就够了。PR 的目的是请求维护者把某个分支的改动合入目标分支。
PR 更像一张改动申请单。
代码只是其中一部分。
解释、讨论、审查和自动化检查同样重要。
PR 的合并方式有几种(merge commit、squash merge、rebase merge),这里不展开。知道”PR 最终的目标是把改动合进目标分支”就够了。
情况一:你是仓库协作者,有写权限
先看第一种场景:你是团队成员,已经被加入了仓库,有写权限。
这种情况下,你的工作流通常是这样的:
1 | clone 仓库 |
简化命令大概是:
1 | git clone git@github.com:owner/repo.git |
注意:你 push 的是同一个仓库里的一个新分支,不是直接 push 到 main。-u 参数是把本地分支和远程分支关联起来,之后直接 git push 就行。
push 完之后,去 GitHub 页面上创建 PR,选好 base branch 和 head branch,写清楚改了什么、为什么改,然后提交。
接下来等两件事:
- 人看:reviewer 审查你的代码,可能会评论、建议修改、或者直接 approve。
- 机器跑:CI(持续集成)自动跑测试、lint、构建等检查。
都通过了,才能合并。
但这里有一个关键点:即使你有写权限,也不一定能直接 push 到 main。
仓库可能设置了分支保护(Branch Protection)。分支保护可以要求:
- 禁止直接 push 到 main
- 必须通过 PR
- 必须至少一个人 review 并 approve
- 必须 CI 通过
- 必须保持分支是最新的(和 main 没有冲突)
- 禁止 force push
- 禁止删除分支
有写权限,不等于可以绕过流程。
分支保护就是为了让主线不被随手改坏。
这些规则是仓库管理员配置的,不是所有仓库都一样。有些仓库的 main 分支完全开放,有些则非常严格。但趋势是:正经项目通常都会对主分支做保护。
情况二:你是外部贡献者,没有写权限
再看第二种场景:你想给一个开源项目修 Bug,但你不是项目成员,没有仓库写权限。
这时候你不能直接往原仓库 push 分支。你需要先 fork。
Fork 是 GitHub 上的一个操作:把别人的仓库复制一份到你自己的账号下。这个副本就是你的 fork。
Fork 的意义不是”复制一份收藏”。它解决的是权限问题:我不能直接改你的仓库,但我可以改自己的副本,再请求你合并。
完整的流程长这样:
1 | Fork 原仓库 |
用图来表示就是:
1 | 原仓库 upstream:owner/repo |
简化命令大概是:
1 | # clone 你自己的 fork |
这里有两个 remote 需要分清:
- origin:通常指向你自己的 fork(
yourname/repo) - upstream:通常指向原项目仓库(
owner/repo)
push 到的是 origin,也就是你自己的 fork。然后去 GitHub 上,从你的 fork 分支向原仓库的目标分支创建 PR。
Fork 不是备份。
它让你在没有写权限的情况下,也能参与到项目中来。
几个注意事项:
- fork 之后要注意同步 upstream 的更新。如果原仓库有了新的 commit,你的 fork 可能会过时,需要定期
git fetch upstream然后合并或 rebase。 - 大项目通常要求先开 Issue 讨论,或者遵守 CONTRIBUTING.md 里的规范。
- 不要把一堆无关的改动塞进同一个 PR。PR 越小越容易 review,越容易合并。
Review 和 CI:为什么 PR 不能马上合并
PR 创建之后,通常不会马上合并。因为维护者需要确认几件事:
- 改动是否真的解决了问题
- 是否引入了新问题
- 代码风格是否符合项目规范
- 测试是否通过
- 文档是否需要更新
- 是否影响兼容性
这些确认工作分两部分:
- Code Review(代码审查):由人来做。reviewer 会看你的代码,评论、提问、建议修改,或者直接 approve。
- CI(持续集成):由机器来做。每次 push 新的 commit,CI 会自动跑测试、lint、构建等检查,把结果报告到 PR 页面上。
1 | Pull Request |
这三件事叠加在一起,构成了 PR 的”把关”机制。
GitHub 的 Code Review 机制允许 reviewer 对具体某一行代码提出评论,也可以用”建议修改”功能直接给出修改建议,作者一键就能应用。reviewer 提交 review 时有三个选项:Comment(只评论)、Approve(批准)、Request Changes(要求修改)。
仓库管理员可以设置”必须至少有 N 个人 approve 才能合并”,这就是 required reviews。
CI 的检查结果会显示在 PR 页面的 Checks 标签页里。绿色勾表示通过,红色叉表示失败。仓库管理员也可以设置”必须所有检查通过才能合并”,这就是 required status checks。
PR 的价值不只是让代码进来。
它还给了项目一个”拦一下”的机会。
这一节不深入 GitHub Actions 的配置,只讲概念。CI 具体怎么跑、用什么工具,是另一个话题。
Branch Protection:为什么主分支不能随便改
前面提到了分支保护,这里单独拿出来讲一下。
主分支通常代表:
- 可以发布的代码
- 团队共同依赖的基线
- CI/CD 的触发源
- 其他开发分支的起点
如果任何人都能直接 push,风险很大。一个人手抖 force push 了一下,可能整个分支的历史就乱了。
分支保护规则可以要求:
- 禁止直接 push:所有改动必须通过 PR
- 禁止 force push:防止覆盖历史
- 禁止删除分支:防止误删
- 必须通过 PR:不能绕过审查流程
- 必须通过状态检查:CI 必须全部通过
- 必须有人 review:至少一个 reviewer approve
- 必须由 Code Owners 审查:特定目录的改动必须由对应的 owner 看过
- 必须保持线性历史:视项目规则而定
分支保护不是不信任开发者。
它是把团队约定变成平台规则。
需要说明的是:分支保护不是所有仓库默认开启的。它需要仓库管理员主动配置,不同项目的规则也不同。有些个人项目可能完全没有分支保护,而企业内部项目通常会配得很严格。
GitHub 近年还推出了 rulesets,这是一种更新的规则管理机制,可以更灵活地对分支和标签设置保护规则。rulesets 和传统的 branch protection rules 有重叠但不完全相同,具体差异可以参考 GitHub 官方文档。如果你只是想理解协作流程,知道”分支保护可以限制谁改什么”就够了。
GitHub Flow:一个常见的轻量协作模型
把前面讲的这些串起来,就得到了一个常见的协作模型,GitHub 官方称之为 GitHub Flow。
核心思路很简单:
1 | main 保持可用 |
这个模型的特点是:
- main 分支始终是可部署的状态
- 所有改动都通过 PR 进入 main
- PR 经过 review 和 CI 检查后才能合并
- 合并后可以自动部署
GitHub Flow 不是唯一的协作流程。有些团队用 Git Flow(更复杂的分支模型),有些用 trunk-based development(所有人在主干上开发),有些用 release branch。但对于很多 Web 服务、开源项目、小团队来说,GitHub Flow 是最容易理解和执行的。
这里不深入比较各种流程。重点是理解:这些流程都建立在”平台提供的协作对象”之上。没有 Issue、PR、Review、Branch Protection 这些东西,流程就无从谈起。
一个完整例子:修一个文档错误
用一个小例子把前面的内容串起来。
场景:你看到某个开源项目 README 里有一处命令写错了。
如果你是协作者
你有仓库的写权限,流程是:
1 | 新建分支 docs-fix-command |
1 | git checkout -b docs-fix-command |
如果你不是协作者
你没有写权限,流程是:
1 | fork 仓库 |
1 | git clone git@github.com:yourname/repo.git |
两种流程最后都是 PR。区别在于你的分支在哪里:
- 协作者:分支在原仓库
- 外部贡献者:分支在自己的 fork
PR 是两条路径的汇合点。
不管你有没有写权限,最后都要把改动放到一个可以被讨论、审查、合并的位置。
常见误区
讲完流程,列几个常见的误解。
1. 以为 PR 是 Git 命令
PR 是平台功能,不是 Git 核心命令。Git 本身只有 commit、branch、merge、remote、push、fetch 这些。PR 是 GitHub(以及 GitLab 的 MR)在 Git 之上提供的协作对象。
2. 以为 Fork 就是备份
Fork 更重要的意义是权限隔离和贡献入口。你 fork 一个仓库,不是为了收藏它,而是为了在没有写权限的情况下,也能改代码、提 PR。
3. 以为有写权限就应该直接 push main
有写权限也应该遵守团队流程。主分支通常应该受保护。直接 push main 跳过了 review 和 CI,是对项目质量的冒险。
4. 以为 Issue 只能报 Bug
Issue 也可以是需求、任务、讨论、文档问题。它是一个通用的”可追踪话题”。
5. 以为 PR 越大越有价值
PR 越大,review 成本越高。reviewer 面对一个改了 50 个文件的 PR,很难认真看完。小而清晰的 PR 更容易被认真审查,也更容易合并。
6. 以为 CI 通过就一定没问题
CI 只能证明已有的检查通过了。它不能替代设计判断和代码审查。一个 CI 全绿的 PR,代码可能照样写得很烂。
7. 以为 fork 之后就和原仓库没关系了
fork 和 upstream 仍然有关系。如果原仓库有了新的 commit,你的 fork 不会自动同步。你需要定期从 upstream 拉取更新,否则你的分支可能和原仓库差得太远,PR 合并时会有一堆冲突。
8. 以为 GitHub 才有这些概念
Pull Request、Issue、Fork、Branch Protection 这类协作概念不是 GitHub 独有的。GitLab 里类似的概念叫 Merge Request(MR),Issue 和 Fork 的叫法一样。Gitea 和 Forgejo 也提供了类似的功能,只是界面和细节不同。核心思想是一样的:在 Git 之上加一层协作机制。
总结:Git 管版本,平台管协作
回过头来看:
- Git 本身负责版本控制——记录谁在什么时候改了什么。
- GitHub 这类平台没有改变 Git 的核心模型。commit 还是 commit,branch 还是 branch。
- 平台在 Git 之上增加了 Issue、Pull Request、Fork、Review、CI、权限和分支保护。
- 协作者通常从原仓库拉分支,改完提 PR。
- 外部贡献者通常 fork 后改自己的副本,再从 fork 向原仓库提 PR。
- 分支保护和 Review 的目的,是保护主线质量。
- PR 的重点不是”把代码传上去”,而是”把改动放进协作流程”。
真正理解 GitHub 协作流程以后,再看 PR、Issue、Fork,就不会觉得它们是一些零散功能了。
它们其实都在回答同一个问题:多人怎么安全地修改同一个项目。
参考资料
- GitHub Docs: About pull requests
- GitHub Docs: About pull request reviews
- GitHub Docs: About issues
- GitHub Docs: About forks
- GitHub Docs: Fork a repository
- GitHub Docs: About protected branches
- GitHub Docs: GitHub flow
- Git Documentation: Branches
- Git Documentation: Remotes
- GitLab Documentation: Merge requests
- 标题: GitHub 到底在 Git 之外做了什么?从 Issue、Fork 到 Pull Request
- 作者: Kaku
- 创建于 : 2026-05-23 17:00:00
- 更新于 : 2026-06-09 18:27:03
- 链接: https://www.kakunet.top/2026/05/23/GitHub-到底在Git之外做了什么/
- 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。