Forking工作流

先说下fork的意思,本义是叉子,引申为分叉,相信很多人对Linux的fork函数都不陌生,在这里指分支分流的意思,你fork一个项目就相当于你在该项目的主分支上又建立了一个分支,owner变成了自己,你可以在该分支上任意修改,如果想将你的修改合并到原项目中时,可以Pull Request,这样原项目的作者觉得你修改了BUG或者有更好的想法就会将你修改的东西合并到原项目的主分支上去,然后你就为开源项目贡献了代码,开源项目就是这样在每个人的共同的努力下不断壮大和完善。所以它也是开源项目理想的协作方案。

和其他工作流一样,fork工作流以一个储存在服务端的远程仓库为开场,新的开发者想参与项目,他们不直接clone,而是fork一份,相当于是在服务端创建了一份副本,之后,他们会执行clone操作,在本地机器上面复制一份,然后对其编辑、暂存、提交,最后推送到自己的公开仓库,然后这个时候可以向主仓库发起一个Pull Request,让项目维护者知道有人参与贡献这个项目代码,并决定是否合并,更进一步,项目维护者可以将贡献者的修改拉取到本地仓库,确保不会破坏项目,将它合并到本地的master分支,然后将master分支推送到服务端的远程仓库,此时,贡献已经是项目的一部分了,其他开发中亦可以从主仓库拉取并同步他们的本地仓库。

接下来举例来说明一下这个工作流是如何工作的:

1. 初始化中央仓库

首先是我们的项目负责人在服务器上创建中央仓库,如果这是一个新项目,你可以初始化一个空的仓库,不然,你需要导入一个已经存在的Git或者SVN项目。

中央仓库应该永远是裸仓库(没有工作目录),命令如下:

ssh user@host
git init --bare /path/to/repo.git

注意这里使用的SSH用户名userhost服务器域名或者IP地址、储存仓库的地址/path/to/repo.git都是有效的。

针对GitHub或者GitLab用户还可以使用图形界面来代替上面的操作。

2. 小张和小李fork仓库

接下来,所有开发者需要 fork 官方仓库。你可以用 SSH 到服务器,运行 git clone 将它复制到服务器的另一个地址—— fork 其实只是服务端的 clone。针对我们的GitHub或者GitLab用户只需要点击一下按钮就可以fork仓库。在这步之后,每个开发者应该都有了自己的服务端仓库。像主仓库一样,所有这些仓库都应该是裸仓库。

3. 小张和小李将 fork 的仓库克隆到本地

接下来他们用之前熟悉的git clone命令来克隆到本地。假设使用GitLab来托管仓库,注意这种情况下,他们都应该有自己的GitLab账号:

git clone https://user@gitlab.com/user/repo.git

与其它工作流不同的是,Fork工作流需要两个远程连接,一个是官方远程仓库,一个是开发者个人的服务端仓库,你可以给这些远端取任何名字,约定origin为fork后的仓库的远端,upstream为官方项目。

git remote add upstream https://github.com/maintainer/repo

你需要使用上面的命令来创建上游仓库的远程连接。它使得你轻易地保持本地仓库和官方仓库的进展同步。注意如果你的上游仓库开启了认证(比如它没有开源),你需要提供一个用户名,就像这样:

git remote add upstream https://user@github.com/maintainer/repo.git

它需要用户从官方代码库克隆或拉取之前提供有效的密码。

3. 小张和小李开发自己的功能

他们还像以前一样编辑、暂存 、提交:

git checkout -b feature-A
# git checkout -b feature-B
git add .
git commit -m "提交说明"

所有的修改都是私有的直到push到自己公开仓库中。如果正式项目已经往前走了,可以使用git pull命令获取到最新:

git pull upstream master

4. 小张发布自己的功能

一旦小张完成了开发,这时候他需要将他的代码贡献到自己的公开仓库,让其它的开发者都可以访问到:

git push origin feature-A

这里和之前的工作流的差异是,origin远程别名指向开发者自己的服务端仓库,而不是正式仓库。

然后,开发者要通知项目维护者,想要合并他的新功能到正式库中。一般GitHub或者GitLab这类三方平台都有类似功能按钮,点击弹出表单让你指定哪个分支合并到正式仓库,一般都是集成自己的功能分支到上游远程仓库的master分支。

5. 小李也发布自己的功能

小李也以同样的方式来发布自己的功能。

6. 项目维护者小王集成小张和小李提交的功能

当小王收到pull request,他要做的是决定是否集成它到正式代码库中。一般有两种方式:

  • 直接在pull request中查看代码

  • pull代码到他自己的本地仓库,再手动合并

第一种方式更简单,小王可以在GUI中查看变更的差异,做评注和执行合并。 但如果出现了合并冲突,需要第二种方式来解决。这种情况下,小王需要从小张或者小李的服务端仓库中fetch功能分支, 合并到他本地的master分支,解决冲突:

git fetch https://github.com/user/repo feature-branch
git checkout master
git merge FETCH_HEAD

一旦修改被整合进本地的 master,小王需要将它推送到服务器上的官方仓库,这样其他开发者也可以访问它:

git push origin master

注意,维护者(小王)的 origin 指向他们的公开仓库,也就是项目的官方代码库。开发者(小张和小李)的贡献现在完全并入了项目。

7. 小张和小李同步官方仓库

因为主代码库已经取得了新的进展,其他开发者应该和官方仓库同步:

git pull upstream master

这样所有人的代码都已经是最新的了,Fork工作流经常用在开源项目中,无论身处何地,任何开发者都可以轻而易举地和其他开发者共享修改,任何分支都能高效地并入主代码库。如果你是一名开源爱好者,一定要掌握好它。