交叉型工作流程跟前面讨论过的流程相比大不相同,不再使用单一的服务器端中心代码仓库,而是给每个开发人员一个服务器端的代码仓库,也就是说每个开发人员都有两个Git仓库:私人的本地仓库和公共的服务器端仓库。
本流程的主要优势是不需要把提交的代码跟别人的代码集成,而以往使用单一中心代码库时则需要经常进行此类操作。开发者只能将自己的代码提交到属于自己的服务器端代码仓库,只有专门的运维人员能够向正式的代码仓库推送代码。运维人员从其他开发人员那里接收提交的代码,而不用向开发人员开放正式代码库的写权限。
交叉型的工作流程为大型的、有机组织的团队(包括具备信任风险的第三方)提供了灵活而安全的协作方式,也是开源项目理想的工作流程。
它是如何工作的
交叉型工作流程在开始的时候也拥有一个正式的公共库,该库保存在服务器端。当一个新的开发人员想要进入项目工作时,他们不直接从正式库克隆。
相反,他们在服务器端创建一个正式库的拷贝,这个新拷贝是他们的个人公共库。其他开发人员不允许向该库推送,但可以从这里拉取变更(稍后将看到这样做是很重要的)。创建了个人的服务器中心库后,开发人员执行git clone把该库的拷贝克隆到本地,作为个人的开发环境,这个其它流程没有什么两样。
开发人员完成开发工作后,将本地提交推送到自己的服务器端公共库(不是正式库),然后创建一个“拉取请求”以便让运维知道有一个更新准备就绪可以用来集成了,这个“拉取请求”同样可以用来发起讨论以便对提交的代码进行评审或解决可能存在的问题。
为了将这个特性集成到正式代码库,运维人员从该贡献者的个人公共库拉取变更到自己的本地仓库、检查以确保变更集不会破坏项目、合并变更到自己的本地master分支、推送这个master分支到服务器端的正式库,现在那个工程师贡献的代码变成了项目的一部分,其他工程师应当从正式库拉取变更以同步他们个人本地库。
正式代码仓库
需要注意的是,交叉型流程里的“正式”代码库这个概念仅仅是一个约定,从技术层面来讲,Git不认为它和其他工程师的公共库有什么不同。这个正式库之所以“正式”是流程约定的,它的用途比较独特,是运维人员的公共库。
交叉型流程的分支操作
所有这些个人公共库可以很高效的跟其他开发人员共享分支,每个人还是应该使用分支隔离独立的特性,就像特性分支流程、Gitflow流程那样,不同的是分支共享的方式不一样,在交叉流程中,分支被拉到其他开发人员的本地库中,而在特性分支流程和Gitflow流程里,分支都被推送到正式库。
示例
项目运维人员初始化正式库
所有基于Git的项目首先都要在服务器建立供团队成员访问的正式库,只不过在这个流程下,正式库只对运维人员开放而已。
初建的恶公共库应该都是空白的,运维人员运行如下命令建立正式库:
ssh user@host
git init --bare /path/to/repo.git
Bitbucket和Stash的GUI工具提供了一个完成上述操作的功能,其他工作流程也是通过上述命令完成中心库的建立的。必要的话,运维人员可以把现有的代码推送到这个库里。
开发人员从正式库建立个人库
下一步,其他开发人员需要从正式库岔出个人库,可以在服务器上执行git clone命令在需要的位置克隆正式库。(岔出的个人库是存储在服务器端的,Bitbucket和Stash的GUI工具也提供了一个完成上述操作的功能)。
完成这个操作后,每个开发人员都有了自己的服务器端的代码库,它们跟正式库一样都是空白的。
开发人员克隆个人库到本地
接下来每个开发人员需要克隆自己的公共库,直接使用git clone命令即可。
这个例子假设使用Bitbucket作为这些个人库的主机,每个开发人员也都有Bitbucket的账号,他们运行如下命令克隆服务器端的个人库:
git clone https://user@bitbucket.org/user/repo.git
以往介绍的流程只使用一个origin指向远端的中心库,但是交叉型流程至少需要两个远端库:一个指向中心正式库,一个指向开发者个人库。这两个远端的名字可以随便取,通常的习惯是使用origin作为开发人员自己服务器端个人库的名称(git clone执行时自动生成),使用upstream作为正式库的名称。
git remote add upstream https://bitbucket.org/maintainer/repo
开发人员需要自己使用上述命令创建upstream远端连接,开发人员使用这个远端连接跟正式库保持一致。如果upstream库需要认证的话,需要提供自己的用户名,比如:
git remote add upstream https://user@bitbucket.org/maintainer/repo.git
将来跟中心库连接时(克隆或拉取)都需要提供对应的密码。
开发人员进行特性开发
在开发人员克隆的本地库里,他们可以跟以前流程里一样进行代码修改、提交变更、创建分支等工作:
git checkout -b some-feature
# Edit some code
git commit -a -m "Add first draft of some feature"
所有这些变更在推送到他们自己的公共库之前完全是私有的,如果正式库的代码已经发生了变化,工程师可以把新的提交记录git pull回来:
git pull upstream master
由于开发人员都在自己专用的特性分支下工作,这个操作一般来说会产生“fast-forward”合并。
开发人员发布特性
开发人员负责的特性开发完毕了,紧接着需要做两件事情。首先,需要把自己的代码推送到服务器上自己的个人库里,以便于其他人员读取。此时,开发人员自己本地的origin远端连接应该已经建立了,他们执行如下命令即可:
git push origin feature-branch
此处跟其他工作流程不同,这里的origin远端连接指向的是开发者在服务器端的个人公共库,而不是正式的主代码库。
其次,开发人员需要通知项目运维人员准备合并自己的特性到正式代码库中。Bitbucket和Stash提供了一个完成“拉取请求”的功能,可以让开发者选择想要合并到正式代码库的具体分支。一般来说,这个合并是要把特性分支合并到upstream远端连接对应的master分支中。
项目运维人员集成这些特性
项目维护人员收到拉取请求后,就要决定是否要将收到的特性集成到正式代码库中,他们可以选择下述两种方式中的一种进行决策:
- 直接在拉取请求里检查代码
- 将这些代码拉取到他的本地代码库并进行手工合并
第一个方式比较简单,运维人员可以查看变更带来的差异、对其进行注释、通过GUI工具进行合并。但是如果拉取请求出现了冲突,使用第二个方式就很有必要了。在这个案例中,运维人员需要从开发人员的服务器端个人库获取特性分支、合并到自己本地的master分支中、解决任何可能的冲突。
git fetch https://bitbucket.org/user/repo feature-branch
# Inspect the changes
git checkout master
git merge FETCH_HEAD
一旦变更被集成到运维人员自己的本地master中后,他们需要将其推送到服务器上的正式库,便于开发人员读取:
git push origin master
开发人员的origin远端指向是项目的正式代码库,开发人员贡献的特性现在就完全集成到项目中来了。
开发人员和正式代码库同步
由于主代码库发生了变化,其他开发人员应当跟正式库保持同步:
git pull upstream master
何去何从
如果你有很深的SVN背景,那么交叉式工作流程似乎显得很激进,但是别担心,很多要做的事情在上面介绍的特性分支流程里已经阐述过了,本流程跟只通过一个中心库进行分支共享的方式不同,开发者提交的代码只被发布到了面向开发者自身的服务器端代码库。
这篇文章介绍了一个开发人员贡献的代码如何整合到master分支,同样的方法论可以被用于集成代码到任何代码库,比如你的团队的部分成员正在一个特定的特性上协同开发,他们可以使用同样的方式共享变更,而不用接触到主代码仓库。
这就使交叉型工作流在组织比较松撒的团队里变得非常强大,任何开发人员能够很容易地共享变更给他人,任意分支能够被高效地整合进正式代码库。
注意:本文归作者所有,未经作者允许,不得转载