在以前,fork 是一个贬义词,指的是某个人使开源项目向不同的方向发展,或者创建一个竞争项目,使得原项目的贡献者分裂。
在 GitHub,fork 指的是在你自己空间中创建的项目副本,这个副本允许你以一种更开放的方式对其进行修改。
——《Pro Git》
无论是对开源项目做贡献,还是在自己团队的项目中进行多人协作开发,了解如何正确的 派生(Fork) 并且创建 拉取请求(Pull Request,简称 PR) 都是必不可少的。
一个较为标准的流程为:
- 派生 一个项目
- 从 master 分支创建一个新分支
- 完成工作,提交 commit
- 创建一个 拉取请求
- 讨论、根据实际情况改进代码
- 项目管理者合并或关闭拉取请求
现在我们来看看具体的流程有哪些。
派生一个项目
无论是著名的 Github,还是 Gitlab,项目主页面都是非常相似的。在项目主页面的右上角,找到 Fork 按钮点击一下,即可在你自己的空间中创建一个项目副本。这即是 派生。
假设用户名是 user
,项目名为 project
。我们接下来将这个项目 克隆(clone) 到本地:
1 | $ git clone [email protected]:user/project.git |
保持项目为最新的状态
如果你只是想在短期内为项目贡献,这是非必须的步骤。
但如果你打算长期为项目作出贡献,或者你自己就是开发团队的一员,则此步必不可少。
要保持项目为最新的状态,需要先添加一个上游仓库:
1 | # 添加一个名为 upstream 的上游仓库地址 |
现在我们已经添加了一个上游仓库的地址,接下来我们从上游仓库中 抓取(fetch) 最新的内容并 合并(merge) 进本地仓库:
1 | # 从上游仓库抓取最新内容 |
如果没有意外,现在本地仓库已经是最新的内容了。
从 master 分支创建一个新分支
如果团队中的每个人都在同一个分支上开发,那这个分支将会变得非常混乱。针对某个特性进行修改或修复错误将会变得非常困难,特别是代码审查和错误排查也将变得难以进行。
所以在开发中合理利用 分支(branch) 是非常重要的事情。
首先,检出(checkout) 将要创建新分支的分支,这里自然就是 master 分支:
1 | # 检出 master 分支 |
然后基于当前分支创建一个新分支:
1 | # 创建一个名为 newfeature 的新分支 |
很明显,branch
命令用于创建分支,但是并不会帮我们切换到新分支上面。如果想要切换到新分支,一样是用 checkout
命令。
但是大部分情况下,我们想要的都是:创建并切换到新分支,这有个快捷的方式:
1 | # 创建一个名为 newfeature 的新分支并切换到这个分支上 |
对于分支的命名,也应遵守一些规范,比如:
- master:主分支,用于生产环境,一般由 develop 和 hotfix 分支合并而成
- develop:主要的开发分支
- feature:基于 develop 分支,开发新功能的分支
- hotfix:基于 master 分支,修复 master 分支上问题的分支
更新、清理分支
当我们完成改进,也在新分支提交了一些 commit,接下来就是将改进的代码上传到远程自己的仓库里,然后创建一个 拉取请求 了。
但是在上传之前,为了让原仓库的所有者更方便的审核并测试代码,我们需要对分支进行一些操作。
在我们工作的同时,原仓库也在更新。所以这时候我们应该先更新到最新的代码,保证我们在本地做的工作不会和原仓库发生冲突。
1 | # 从上游仓库抓取最新内容,并将上游仓库的更新合并进本地 master 分支 |
在更新原仓库的内容之后,就是清理我们的 commit。在实际开发中,我们经常会提交一些相似的、细碎的 commit,所以我们在上传代码之前应该先清理一下。
1 | $ git checkout |
现在可以上传我们的改进了。
创建拉取请求
上传代码之后,我们就可以去自己的仓库页面点击 New pull request 按钮,即可发起一个 拉取请求。
发起之后,就可以等待原仓库的所有者对这个请求进行合并、拒绝或是发表评论了。
结束
本文只是描述如何用较为标准的方式参与一个开源项目。其中使用到的一些东西,比如 **变基(rebase)**,内容太多,讲起来可能会偏离本文的主题,所以并没有过多的说明,未来可能会单独拿出来讲。
最后祝大家没有机会使用到 hotfix 分支😀。