本文章也可以先看玄离199本文章有些图片来源此视频个人开发多人协作思路大致回到需要合并的分支然后拉取同步再合并这3步缺一不可一、为什么需要这套流程原理是什么1. 传统模式的问题你之前习惯的commit → push如果你和同事都在同一个仓库的主分支如main上直接 push后 push 的人必须先解决冲突很容易覆盖别人的代码。没有代码审查Code Review任何错误都可能直接上线。无法进行持续集成CI自动测试问题难以提前发现。2. Fork PR 模式的优点Fork派生将主仓库完整复制一份到你自己的账号下相当于你的“私人工作区”。你可以在自己的 fork 里任意修改不会影响主仓库。分支Branch每个新功能或修复都在独立的分支上开发避免不同任务之间的代码混杂。Pull RequestPR向原仓库发起合并请求。它提供了代码审查和自动化测试的触发点。只有经过审查和测试的分支才能合并到主分支。保护主分支主分支如main只接受经过 PR 合并的代码始终保持稳定可发布状态。3. 完整流程的逻辑链条text1. 主仓库上游 ← 2. Fork你的副本 ← 3. Clone 到本地 4. 创建新分支 → 5. 开发 测试 → 6. Push 到你的远程 fork 7. 发起 PR → 8. 团队成员 Review → 9. 根据反馈修改 → 10. 合并完整操作步骤以 GitHub 为例1. Fork (派生分支)原仓库打开上游仓库页面点击右上角Fork按钮选择 fork 到你的账号下2. 克隆你的 fork 到本地git clone https://github.com/你的用户名/仓库名.git cd 仓库名cd 仓库名就是让你进入这个仓库的根目录让后续所有 Git 命令能够正确运行添加上游仓库地址git remote add upstream ...的本质是修改当前仓库的配置写入.git/config文件。只有当你身处该仓库的根目录时git remote命令才知道要修改哪个仓库的配置。如果你没 cd 进去Git 找不到仓库自然无法添加 upstream即cd 仓库名是为了让你站在 Git 仓库的“内部”这样所有 Git 命令才能知道要操作哪个仓库添加 upstream 地址是仓库级别的配置必须先 cd 进去。3. 添加上游仓库地址用于同步git remote add upstream https://github.com/原仓库拥有者/仓库名.git git remote -v # 验证origin 是你的 forkupstream 是原仓库背景知识当你clone你自己的 fork 时Git 会自动创建一个默认的远程仓库名字叫origin指向你的 fork你的用户名/仓库名.git。但你的本地仓库并不认识原始项目上游仓库的地址所以你需要手动告诉它。第一个命令给你的本地仓库添加一个指向原始项目仓库的远程地址并给它起个名字叫upstream。这条命令的组成部分git remote add→ 添加一个远程仓库记录upstream→ 你给这个远程仓库起的名字可以任意但社区约定俗成用upstreamhttps://github.com/原仓库拥有者/仓库名.git→ 原始项目的真实地址执行完后你的本地仓库就知道origin是 我的 forkupstream是 原作者的项目二、为什么需要添加upstream因为原始项目上游仓库会不断更新比如别人合并了新的 PR。如果没有upstream你就无法从原始项目拉取最新代码你的 fork 会逐渐落后将来你提交 PR 时就会产生很多冲突。有了upstream你可以随时运行bashgit fetch upstream # 拉取原始项目的最新代码 git merge upstream/main # 将原始项目的 main 分支合并到你的本地 main从而保持你的代码和原始项目同步。第二个命令git remote -v-v是--verbose的缩写意思是显示所有远程仓库的详细地址。执行后会输出类似textorigin https://github.com/你的用户名/仓库名.git (fetch) origin https://github.com/你的用户名/仓库名.git (push) upstream https://github.com/原仓库拥有者/仓库名.git (fetch) upstream https://github.com/原仓库拥有者/仓库名.git (push)验证的目的确认upstream确实添加成功并且 URL 写对了没有拼错用户名或仓库名。确认origin仍然指向你自己的 fork确保后续 push 不会推到错误的地方。4. 创建新分支基于上游最新 mainbashgit fetch upstream # 获取上游最新代码 git checkout -b my-feature upstream/main # 创建并切换到新分支一、git fetch upstream这条命令的作用是从你添加的upstream远程仓库即原始项目仓库下载所有最新的内容新提交、分支、标签等但不会合并到你当前的任何本地分支中。执行后Git 会在本地生成一组“远程跟踪分支”比如upstream/main、upstream/develop等。这些分支代表了上游仓库各个分支的最新状态。为什么需要这一步因为你的本地仓库原本只知道origin/main你自己的 fork 的主分支和可能旧的本地main。如果不先fetch你的本地就没有upstream/main这个“指针”也就无法基于上游最新代码创建新分支。它并不是“存为一个文件”而是更新 Git 内部的一个指针指向上游main分支最新提交的位置。可以认为执行后upstream/main就代表了上游main的最新状态。git fetch upstream就是去上游仓库看了一眼把“上游各分支现在长什么样”的信息记在本地的笔记本里即upstream/main等指针但你的工作区你正在编辑的代码文件不会有任何变化这个“笔记本”就是.git/refs/remotes/upstream/下的文件二、git checkout -b my-feature upstream/main这条命令做了两件事checkout -b my-feature创建一个新分支名字叫my-feature并立即切换到这个分支。upstream/main指定了新分支的起点基准也就是基于上游仓库的main分支当前的最新状态来创建。等价于bashgit branch my-feature upstream/main # 创建分支但不切换 git checkout my-feature # 切换到该分支为什么不能用git checkout -b my-feature main如果你用main本地main作为起点而你的本地main可能已经落后于上游因为别人合并了 PR 你没有同步那么你创建的新分支就会基于一个过时的版本后续提交 PR 时会产生额外的合并冲突。用upstream/main可以确保你的新分支直接基于上游仓库的最新代码这样将来提交 PR 时差异最干净冲突最少。三、整个流程的逻辑链条text1. git fetch upstream → 将上游的最新状态同步到本地存为 upstream/main 2. git checkout -b my-feature upstream/main → 基于刚刚获取的上游 main 分支创建一个新的本地分支这样你的my-feature分支就等同于从上游的 main 分出来的就像是你在上游仓库直接创建了一个分支一样。之后再开发、提交、push 到origin你自己的 fork然后发起 PRPR 的目标分支就是上游的mainGitHub 会自动发现你的分支是基于上游最新代码的不会有额外的合并提交总结fetch刷新笔记本里的upstream/main指针checkout -b则读取这个指针作为新分支的起点即上游仓库main分支的最新代码5. 开发 本地测试使用编辑器修改代码运行项目要求的测试如npm test、pytest等确保全部通过6. 提交并推送到你的 forkbashgit add . git commit -m feat: 添加某个功能 git push origin my-feature # 推送到你的 fork 仓库的对应分支git push origin my-feature推送到你自己的远程 fork 仓库即origin指向的那个 GitHub 仓库。这个仓库是你的副本你有完全的写权限git push origin my-feature将本地my-feature分支上的提交推送到你自己的远程 fork 仓库即origin指向的那个 GitHub 仓库。这个仓库是你的副本你有完全的写权限。问题问“提交到自己的远程私有仓库”如果原仓库是公开的你的 fork 默认也是公开的不是私有但只有你有写权限。如果你手动把 fork 设为私有那才是私有仓库。通常我们称它为“你自己的远程仓库”或者“你的 fork”不一定私有但归你控制。推送之后你的my-feature分支就会出现在 GitHub 上你自己的 fork 仓库里然后你就可以去发起 Pull Request从origin/my-feature到upstream/main。现在只剩下最后一步“发起 PR”和“审查合并”。如果你现在就想尝试可以实际 push 一次然后在 GitHub 上点 “Compare pull request” 按钮7. 创建 Pull Request打开你的 fork 仓库页面GitHub你会看到一个提示“my-feature had recent pushes”旁边有Compare pull request按钮点击Compare pull request按钮填写 PR 标题和描述说明改动内容、测试情况点击Create pull request8. 代码审查与修改维护者或团队成员在 PR 下评论提出修改意见你回到本地切换到该分支bashgit checkout my-feature # 根据意见修改代码再次本地测试 git add . git commit -m fix: 根据 review 意见修改 git push origin my-feature # PR 会自动更新重复直到审查通过9. 合并当所有人都 审查通过approve批准且所有自动化测试CI绿色通过后维护者会点击Merge pull request按钮将你的分支合并进主分支。你的代码正式合并到上游主分支合并后你可以删除自己的远程分支可选并同步更新本地仓库。10. 同步你的 fork可选但推荐bashgit checkout main git pull upstream main # 拉取上游最新 main git push origin main # 同步到你的 fork git branch -d my-feature # 删除本地分支 git push origin --delete my-feature # 删除远程分支关键要点提醒不要直接在上游仓库 push→ 使用 fork PR每个功能一个独立分支→ 保持隔离方便回滚提交前必须本地测试→ 避免浪费 CI 资源PR 内可以多次 push→ 自动更新无需重新建 PR定期同步 upstream→ 减少合并冲突二·、一些小提示为什么要先 fork 而不是直接 clone 原仓库因为你没有原仓库的写入权限fork 让你有自己可写的一份拷贝然后通过 PR 提出贡献。为什么要在新分支开发如果直接用 main 分支当你提交 PR 后又想开发另一个功能两个功能会混在一起。分支保持了功能隔离。测试一定要在本地跑这是你描述中强调的“自己跑一下测试”避免 CI 流水线浪费资源。Review 后再更改PR 评论系统会自动组织多次修改的会话最终合并前会确保所有讨论都 resolved。三、你可以尝试的练习找一个你喜欢的开源项目或创建一个测试仓库按照上面的步骤模拟一次 PR 流程。你甚至可以和自己协作用两个 GitHub 账号或者让一个朋友扮演 reviewer。使用git log --oneline --graph查看分支演变加深理解。最后Fork 和 clone 整个仓库只做一次。之后每天加新模块只需要“同步上游 → 切新分支 → 开发 → push → 开 PR → 等合并”。其中第 1-3 步主仓库 → Fork → Clone 到本地 添加 upstream只需要在刚开始接触项目时做一次。之后的每一次新增小模块、修 bug 或加功能只需要重复第 4-10 步中的一部分。一、一次性初始化只做一次当你第一次给某个项目贡献代码时需要做这些准备Fork 主仓库在 GitHub 网页上点一下按钮Clone 你的 fork 到本地添加 upstream 远程地址git remote add upstream ...做完这三步你的本地环境和远程 fork 就都准备好了。以后不用再做。二、每天新增模块时的日常流程可以简化成 6 步假设你已经完成了上面的初始化。现在你每天要开发一个新模块新功能或修复需要重复的步骤是同步上游最新代码避免冲突bashgit fetch upstream git checkout main git merge upstream/main git push origin main基于最新的 main 创建新分支bashgit checkout -b feat/新模块名 main在分支上开发 本地测试提交并 push 到自己的远程 forkbashgit add . git commit -m feat: 添加新模块 git push origin feat/新模块名发起 PR在 GitHub 网页上点按钮根据 review 反馈修改只需继续 push 到同一个分支PR 自动更新→ 等待维护者合并不需要重新 fork不需要重新 clone不需要重新添加 upstream。三、对比表格更清晰步骤描述初次接触项目时每天新增模块时1主仓库 ← Fork✅ 需要一次❌ 不需要2Clone 到本地✅ 需要一次❌ 不需要3添加 upstream✅ 需要一次❌ 不需要4创建新分支✅ 每次都需要✅ 每次都需要5开发 测试✅ 每次都需要✅ 每次都需要6Push 到你的远程 fork✅ 每次都需要✅ 每次都需要7发起 PR✅ 每次都需要✅ 每次都需要8Review✅ 每次都需要✅ 每次都需要9根据反馈修改✅ 每次都需要✅ 每次都需要10合并✅ 每次都需要✅ 每次都需要即第二次、第三次……开发新模块时你只需要做text4. git fetch upstream git checkout -b new-feature upstream/main 5. 开发 测试 6. git add . git commit -m ... git push origin new-feature 7. 创建 PR 8. 根据 review 修改 9. 等待合并 10. (合并后) git checkout main git pull upstream main git push origin main