BY 童仲毅(geeeeeeeeek@github)git
这是一篇在原文(BY atlassian)基础上演绎的译文。除非另行注明,页面上全部内容采用知识共享-署名(CC BY 2.5 AU)协议共享。github
多种多样的工做流使得在项目中实施Git时变得难以选择。这份教程提供了一个出发点,调查企业团队最多见的Git工做流。缓存
阅读的时候,请记住工做流应该是一种规范而不是金科玉律。咱们但愿向你展现全部工做流,让你融会贯通,因地制宜。安全
这份教程讨论了下面四种工做流:服务器
过渡到分布式分版本控制系统看起来是个使人恐惧的任务,但你没必要为了利用Git的优势而改变你现有的工做流。你的团队仍然能够用之前SVN的方式开发项目。markdown
然而,使用Git来驱动你的开发工做流显示出了一些SVN没有的优势。首先,它让每一个开发者都有了本身 本地 的完整项目副本。隔离的环境使得每一个开发者的工做独立于项目的其它修改——他们能够在本身的本地仓库中添加提交,彻底无视上游的开发,直到须要的时候。app
第二,它让你接触到了Git鲁棒的分支和合并模型。和SVN不一样,Git分支被设计为一种故障安全的机制,用来在仓库之间整合代码和共享更改。框架
和Subversion同样,中心化的工做流将中央仓库做为项目中全部修改的惟一入口。和trunk
不一样,默认的开发分支叫作master
,全部更改都被提交到这个分支。这种工做流不须要master
以外的其它分支。ssh
开发者将中央仓库克隆到本地后开始工做。在他们的本地项目副本中,他们能够像SVN同样修改文件和提交更改;不过,这些新的提交被保存在 本地 ——它们和中央仓库彻底隔离。这使得开发者能够将和上游的同步推迟到他们方便的时候。分布式
为了向官方项目发布修改,开发者将他们的本地master
分支“推送”到中央仓库。这一步等同于svn commit
,除了Git添加的是全部不在中央master
分支上的本地提交。
中央仓库表明官方项目,所以它的提交历史应该被视做神圣不可更改的。若是开发者的本地提交和中央仓库分叉了,Git会拒绝将他们的修改推送上去,由于这会覆盖官方提交。
在开发者发布他们的功能以前,他们须要fetch更新的中央提交,在它们之上rebase本身的更改。这就像是:“我想要在其余人的工做进展之上添加个人修改。”它会产生完美的线性历史,就像和传统的SVN工做流同样。
若是本地修改和上游提交冲突时,Git会暂停rebase流程,给你机会手动解决这些冲突。Git很赞的一点是,它将git status
和git add
命令同时用来生成提交和解决合并冲突。这使得开发者可以垂手可得地管理他们的合并。另外,若是他们改错了什么,Git让他们轻易地退出rebase过程,而后重试(或者找人帮忙)。
让咱们一步步观察一个普通的小团队是如何使用这种工做流协做的。咱们有两位开发者,John和Mary,分别在开发两个功能,他们经过中心化的仓库共享代码。
首先,须要有人在服务器上建立中央仓库。若是这是一个新项目,你能够初始化一个空的仓库。否则,你须要导入一个已经存在的Git或SVN项目。
中央仓库应该永远是裸仓库(没有工做目录),能够这样建立:
ssh user@host git init --bare /path/to/repo.git
但确保你使用的SSH用户名user
、服务器host
的域名或IP地址、储存仓库的地址/path/to/repo.git
是有效的。注意.git
约定俗成地出如今仓库名的后面,代表这是一个裸仓库。
接下来,每一个开发者在本地建立一份完整项目的副本。使用git clone
命令:
git clone ssh://user@host/path/to/repo.git
当你克隆仓库时,Git自动添加了一个名为origin
的远程链接,指向“父”仓库,以便你之后和这个仓库交换数据。
在他的本地仓库中,John能够用标准的Git提交流程开发功能:编辑、缓存、提交。若是你对缓存区还不熟悉,你也能够不用记录工做目录中每次的变化。因而你建立了一个高度集中的提交,即便你已经在本地作了不少修改。
git status # 查看仓库状态 git add <some-file> # 缓存一个文件 git commit # 提交一个文件</some-file>
记住,这些命令建立的是本地提交,John能够周而复始地重复这个过程,而不用考虑中央仓库。对于庞大的功能,须要切成更简单、原子化的片断时,这个特性就颇有用。
同时,Mary在她本身的本地仓库用相同的编辑/缓存/提交流程开发她的功能。和John同样,她不须要关心中央仓库的进展,她也 彻底 不关心John在他本身仓库中作的事,由于全部本地仓库都是私有的。
一旦John完成了他的功能,他应该将本地提交发布到中央仓库,这样其余项目成员就能够访问了。他可使用git push
命令,就像:
git push origin master
记住,origin
是John克隆中央仓库时指向它的远程链接。master
参数告诉Git试着将origin
的master
分支变得和他本地的master
分支同样。中央仓库在John克隆以后尚未进展,所以这个推送如他所愿,没有产生冲突。
John已经成功地将他的更改发布到了中央仓库上,看看当Mary试着将她的功能推送到上面时会发生什么。她可使用同一个推送命令:
git push origin master
可是,她的本地历史和中央仓库已经分叉了,Git会拒绝这个请求,并显示一段冗长的错误信息:
error: failed to push some refs to '/path/to/repo.git' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Merge the remote changes (e.g. 'git pull') hint: before pushing again. hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Git防止Mary覆盖官方的修改。她须要将John的更新拉取到她的仓库,和她的本地修改整合后,而后重试。
Mary可使用git pull
来将上游修改并入她的仓库。这个命令和svn update
很像——它拉取整个上游提交历史到Mary的本地仓库,并和她的本地提交一块儿整合:
git pull --rebase origin master
--rebase
选项告诉Git,在同步了中央仓库的修改以后,将Mary全部的提交移到master
分支的顶端,以下图所示:
若是你忽略这个选项拉取一样会成功,只不过你每次和中央仓库同步时都会多出一个“合并提交”。在这种工做流中,rebase和生成一个合并提交相比,老是一个更好的选择。
Rebase的工做是将每一个本地提交一个个转移到更新后的master
分支。也就是说,你能够一个个提交分别解决合并冲突,而不是在一个庞大的合并提交中解决。它会让你的每一个提交保持专一,并得到一个干净的项目历史。另外一方面,你更容易发现bug是在哪引入的,若是有必要的话,用最小的代价回滚这些修改。
若是Mary和John开发的功能没有关联,rebase的过程不太可能出现冲突。但若是出现冲突时,Git在当前提交会暂停rebase,输出下面的信息,和一些相关的指令:
CONFLICT (content): Merge conflict in <some-file>
Git的优势在于 每一个人 都能解决他们本身的合并冲突。在这个例子中,Mary只需运行一下git status
就能够发现问题是什么。冲突的文件会出如今未合并路径中:
# Unmerged paths: # (use "git reset HEAD <some-file>..." to unstage) # (use "git add/rm <some-file>..." as appropriate to mark resolution) # # both modified: <some-file>
接下来,修改这些文件。若是她对结果满意了,和往常同样缓存这些文件,而后让git rebase
完成接下来的工做:
git add <some-file> git rebase --continue
就是这样。Git会继续检查下个提交,对冲突的提交重复这个流程。
若是你这时候发现不知道本身作了什么,不要惊慌。只要运行下面的命令,你就会回到开始以前的状态:
git rebase --abort
在她和中央仓库同步以后,Mary能够成功地发布她的修改:
git push origin master
正如你所见,使用一丢丢Git命令来复制一套传统的Subversion开发环境也是可行的。这对于从SVN转变而来的团队来讲很棒,但这样没有利用到Git分布式的本质。
若是你的团队已经习惯了中心化的工做流,但但愿提升协做效率,那么探索Feature分支工做流的好处是彻底值当的。每一个功能在专门的独立分支上进行,在代码并入官方项目以前就能够启动围绕新修改的深度讨论。
一旦你掌握了中心化工做流的使用姿式,在你的开发流程中添加功能分支是一个简单的方式,来促进协做和开发者之间的交流。这种封装使得多个开发者专一本身的功能而不会打扰主代码库。它还保证master
分支永远不会包含损坏的代码,给持续集成环境带来了是很大的好处。
封装功能的开发使得pull request的使用成为可能,用来启动围绕一个分支的讨论。它给了其余开发者在功能并入主项目以前参与决策的机会。或者,若是你开发功能时卡在一半,你能够发起一个pull request,向同事寻求建议。重点是,pull request使得你的团队在评论其余人的工做时变得很是简单。
Feature分支工做流一样使用中央仓库,master
一样表明官方的项目历史。可是,与其直接提交在本地的master
分支,开发者每次进行新的工做时建立一个新的分支。Feature分支应该包含描述性的名称,好比animated-menu-items
(菜单项动画)或issue-#1061
。每一个分支都应该有一个清晰、高度集中的目的。
Git在技术上没法区别master
和功能分支,因此开发者能够在feature分支上编辑、缓存、提交,就和中心化工做流中同样。
此外,feature分支能够(也应该)被推送到中央仓库。这使得你和其余开发者共享这个功能,而又不改变官方代码。既然master
只是一个“特殊”的分支,在中央仓库中储存多个feature分支不会引出什么问题。固然了,这也是备份每一个开发者本地提交的好办法。
除了隔离功能开发以外,分支使得经过pull request讨论修改为为可能。一旦有人完成了一个功能,他们不会当即将它并入master
。他们将feature分支推送到中央服务器上,发布一个pull request,请求将他们的修改并入master
。这给了其余开发者在修改并入主代码库以前审查的机会。
代码审查是pull request的主要好处,但他们事实上被设计为成为讨论代码的通常场所。你能够把pull request看做是专一某个分支的讨论版。也就是说他们能够用于开发流程以前。好比,一个开发者在某个功能上须要帮助,他只需发起一个pull request。感兴趣的小伙伴会自动收到通知,看到相关提交中的问题。
一旦pull request被接受了,发布功能的行为和中心化的工做流是同样的。首先,肯定你本地的master
和上游的master
已经同步。而后,将feature分支并入master
,将更新的master
推送回中央仓库。
下面这个🌰演示了代码审查使用到的pull request,但记住pull request有多种用途。
在她开始开发一个功能以前,Mary须要一个独立的分支。她能够用下面的命令建立新分支:
git checkout -b marys-feature master
一个基于master
、名为marys-feature
的分支将会被checkout,-b
标记告诉Git在分支不存在时建立它。在这个分支上,Mary和往常同样编辑、缓存、提交更改,用足够多的提交来构建这个功能:
git status git add <some-file> git commit
Mary在早上给她的功能添加了一些提交。在她去吃午餐前,将她的分支推送到中央仓库是个不错的想法。这是一种方便的备份,但若是Mary和其余开发者一块儿协做,他们也能够看到她的初始提交了。
git push -u origin marys-feature
这个命令将marys-feature
推送到中央仓库(origin
),-u
标记将它添加为远程跟踪的分支。在设置完跟踪的分支以后,Mary调用不带任何参数的git push
来推送她的功能。
当Mary吃完午餐回来,她完成了她的功能。在并入master
以前,她须要发布一个pull request,让其余的团队成员知道她所作的工做。但首先,她应该保证中央仓库包含了她最新的提交:
git push
而后,她在她的Git界面上发起了一个pull request,请求将marys-feature
合并进master
,团队成员会收到自动的通知。Pull request的好处是,评论显示在相关的提交正下方,方便讨论特定的修改。
Bill收到了pull request,而且查看了marys-feature
。他决定在并入官方项目以前作一些小修改,经过pull request和Mary进行了沟通。
为了作这些更改,Mary重复了以前建立功能时相同的流程,她编辑、缓存、提交、将更新推送到中央仓库。她全部的活动显示在pull request中,Bill能够一直评论。
若是Bill想要的话,也能够将marys-feature
pull到他本身的本地仓库,继续工做。后续的任何提交都会显示在pull request上。
一旦Bill准备接受这个pull request,某我的(Bill或者Mary均可)须要将功能并入稳定的项目:
git checkout master git pull git pull origin marys-feature git push
首先,无论是谁在执行合并,都要保证他们的master
分支是最新的。而后,运行git pull origin marys-feature
合并中央仓库的marys-feature
副本。你也可使用简单的git merge marys-feature
,但以前的命令保证你拉取下来的必定是功能分支最新的版本。最后,更新的master
须要被推送回origin
。
这个过程致使了一个合并提交。一些开发者喜欢它,由于它是功能和其他代码合并的标志。但,若是你但愿获得线性的历史,你能够在执行merge以前将功能rebase到master
分支的顶端,产生一个快速向前的合并。
一些界面会自动化接受pull request的流程,只需点击一下“Merge Pull Request”。若是你的没有的话,它至少在合并以后应该能够自动地关闭pull request。
Mary和Bill一块儿开发marys-feature
,在pull request上讨论的同时,John还在开发他本身的feature分支。经过将功能用不一样分支隔离开来,每一个人能够独立地工做,但很容易和其余开发者共享修改。
为了完全了解Github上的功能分支,你应该查看使用分支一章。如今,你应该已经看到了功能分支极大地加强了中心化工做流中单一master
分支的做用。除此以外,功能分支还便利了pull request的使用,在版本控制界面上直接讨论特定的提交。Gitflow工做流是管理功能开发、发布准备、维护的常见模式。
下面的Gitflow工做流一节源于nvie网站上的做者Vincent Driessen。
Gitflow工做流围绕项目发布定义了一个严格的分支模型。有些地方比功能分支工做流更复杂,为管理大型项目提供了鲁棒的框架。
和功能分支工做流相比,这种工做流没有增长任何新的概念或命令。它给不一样的分支指定了特定的角色,定义它们应该如何、何时交流。除了功能分支以外,它还为准备发布、维护发布、记录发布分别使用了单独的分支。固然,你还能享受到功能分支工做流带来的全部好处:pull request、隔离实验和更高效的协做。
Gitflow工做流仍然使用中央仓库做为开发者沟通的中心。和其余工做流同样,开发者在本地工做,将分支推送到中央仓库。惟一的区别在于项目的分支结构。
和单独的master
分支不一样,这种工做流使用两个分支来记录项目历史。master
分支储存官方发布历史,develop
分支用来整合功能分支。同时,这还方便了在master
分支上给全部提交打上版本号标签。
工做流剩下的部分围绕这两个分支的差异展开。
每一个新功能都放置在本身的分支中,能够在备份/协做时推送到中央仓库。可是,与其合并到master
,功能分支将开发分支做为父分支。当一个功能完成时,它将被合并回develop
。功能永远不该该直接在master
上交互。
注意,功能分支加上develop
分支就是咱们以前所说的功能分支工做流。可是,Gitflow工做流不止于此。
一旦develop
分支的新功能足够发布(或者预先肯定的发布日期即将到来),你能够从develop
分支fork一个发布分支。这个分支的建立开始了下个发布周期,只有和发布相关的任务应该在这个分支进行,如修复bug、生成文档等。一旦准备好了发布,发布分支将合并进master
,打上版本号的标签。另外,它也应该合并回develop
,后者可能在发布启动以后有了新的进展。
使用一个专门的分支来准备发布确保一个团队完善当前的发布,其余团队能够继续开发下一个发布的功能。它还创建了清晰的开发阶段(好比说,“这周咱们准备4.0版本的发布”,而咱们在仓库的结构中也能看到这个阶段)。
一般咱们约定:
develop
建立分支master
分支release-* or release/*
维护或者“紧急修复”分支用来快速给产品的发布打上补丁。这是惟一能够从master
上fork的分支。一旦修复完成了,它应该被并入master
和develop
分支(或者当前的发布分支),master
应该打上更新的版本号的标签。
有一个专门的bug修复开发线使得你的团队可以处理issues,而不打断其余工做流或是要等到下一个发布周期。你能够将维护分支看做在master
分支上工做的临时发布分支。
下面的栗子演示了这种工做流如何用来管理发布周期。假设你已经建立了中央仓库。
你要作的第一步是为默认的master
分支建立一个互补的develop
分支。最简单的办法是在本地建立一个空的develop
分支,将它推送到服务器上:
git branch develop git push -u origin develop
这个分支将会包含项目中全部的历史,而master
将包含不彻底的版本。其余开发者应该将中央仓库克隆到本地,建立一个分支来追踪develop分支:
git clone ssh://user@host/path/to/repo.git git checkout -b develop origin/develop
如今全部人都有了一份历史分支的本地副本。
咱们的栗子从John和Mary在不一样分支上工做开始。他们都要为本身的功能建立单独的分支。他们的功能分支都应该基于develop
,而不是master
:
git checkout -b some-feature develop
他们都使用“编辑、缓存、提交”的通常约定来向功能分支添加提交:
git status git add <some-file> git commit
在添加了一些提交以后,Mary确信她的功能以及准备好了。若是她的团队使用pull request,如今正是发起pull request的好时候,请求将她的功能并入develop
分支。不然,她能够向下面同样,将它并入本地的develop
分支,推送到中央仓库:
git pull origin develop git checkout develop git merge some-feature git push git branch -d some-feature
第一个命令在尝试并入功能分支以前确保develop
分支已经是最新。注意,功能毫不该被直接并入master
。冲突的处理方式和中心化工做流相同。
当John仍然在他的功能分支上工做时,Mary开始准备项目的第一个官方发布。和开发功能同样,她新建了一个分支来封装发布的准备工做。这也正是发布的版本号建立的一步:
git checkout -b release-0.1 develop
这个分支用来整理提交,充分测试,更新文档,为即将到来的发布作各类准备。它就像是一个专门用来完善发布的功能分支。
一旦Mary建立了这个分支,推送到中央仓库,此次发布的功能便被锁定了。不在develop
分支中的功能将被推迟到下个发布周期。
一旦发布准备稳妥,Mary将它并入master
和develop
,而后删除发布分支。合并回develop
很重要,由于可能已经有关键的更新添加到了发布分支上,而开发新功能须要用到它们。一样的,若是Mary的团队重视代码审查,如今将是发起pull request的完美时机。
git checkout master git merge release-0.1 git push git checkout develop git merge release-0.1 git push git branch -d release-0.1
发布分支是功能开发(develop
)和公开发布(master)之间的过渡阶段。不论何时将提交并入master
时,你应该为提交打上方便引用的标签:
git tag -a 0.1 -m "Initial public release" master git push --tags
Git提供了许多钩子,即仓库中特定事件发生时被执行的脚本。当你向中央仓库推送master
分支或者标签时,你能够配置一个钩子来自动化构建公开发布。
正式发布以后,Mary回过头来和John一块儿为下一个发布开发功能。这时,一个终端用户开了一个issue抱怨说当前发布中存在一个bug。为了解决这个bug,Mary(或John)从master
建立了一个维护分支,用几个提交修复这个issue,而后直接合并回master
。
git checkout -b issue-#001 master # Fix the bug git checkout master git merge issue-#001 git push
和发布分支同样,维护分支包含了develop
中须要的重要更新,所以Mary一样须要执行这个合并。接下来,她能够删除这个分支了:
git checkout develop git merge issue-#001 git push git branch -d issue-#001
如今,但愿你已经很熟悉中心化的工做流、功能分支工做流和Gitflow工做流。你应该已经能够抓住本地仓库、推送/拉取模式,和Git鲁棒的分支和合并模型的无限潜力。
请记住,教程中呈现的工做流只是可行的实践——而非工做中使用Git的金科玉律。所以,尽情地取其精华,去其糟粕吧。不变的是要让Git为你所用,而不是相反。
Fork工做流和教程中讨论的其它工做流大相径庭。与其使用惟一的服务端仓库做为”中央“代码库,它给予 每一个 开发者一个服务端仓库。也就是说每一个贡献者都有两个Git仓库,而不是一个:一个私有的本地仓库和一个公开的服务端仓库。
Fork工做流的主要优势在于贡献能够轻易地整合进项目,而不须要每一个人都推送到单一的中央仓库。开发者推送到他们 本身的 服务端仓库,只有项目管理者能够推送到官方仓库。这使得管理者能够接受任何开发者的提交,却不须要给他们中央仓库的权限。
结论是,这种分布式的工做流为大型、组织性强的团队(包括不可信的第三方)提供了安全的协做方式。它同时也是开源项目理想的工做流。
和其它Git工做流同样,Fork工做流以一个储存在服务端的官方公开项目开场。但新的开发者想参与项目时,他们不直接克隆官方项目。
取而代之地,他们fork一份官方项目,在服务端建立一份副本。这份新建的副本做为他们私有的公开仓库——没有其余开发者能够在上面推送,但他们能够从上面拉取修改(在后面咱们会讨论为何这一点很重要)。在他们建立了服务端副本以后,开发者执行git clone
操做,在他们的本地机器上复制一份。这是他们私有的开发环境,正如其余工做流中同样。
当他们准备好发布本地提交时,他们将提交推送到本身的公开仓库——而非官方仓库。而后,他们向主仓库发起一个pull request,让项目维护者知道一个更新作好了合并的准备。若是贡献的代码有什么问题的话,Pull request能够做为一个方便的讨论版。
我为了将功能并入官方代码库,维护者将贡献者的修改拉取到他们的本地仓库,确保修改不会破坏项目,将它合并到本地的master
分支,而后将master
分支推送到服务端的官方仓库。贡献如今已经是项目的一部分,其余开发者应该从官方仓库拉取并同步他们的本地仓库。
“官方”仓库这个概念在Fork工做流中只是一个约定,理解这一点很重要。从技术的角度,Git并看不出每一个开发者和官方的公开仓库有什么区别。事实上,官方仓库惟一官方的缘由是,它是项目维护者的仓库。
全部这些我的的公开仓库只是一个在开发者之间共享分支的约定。每一个人仍然可使用分支来隔离功能,就像在功能分支工做流和Gitflow工做流中同样。惟一的区别在于这些分支是如何开始的。在Fork工做流中,它们从另外一个开发者的本地仓库拉取而来,而在功能分支和Gitflow分支它们被推送到官方仓库。
和任何基于Git的项目同样,第一步是在服务端建立一个能够被全部项目成员访问到的官方仓库。通常来讲,这个仓库同时仍是项目维护者的公开仓库。
公开的仓库应该永远是裸的,无论它们是否表明官方代码库。因此项目维护者应该运行下面这样的命令来设置官方仓库:
ssh user@host git init --bare /path/to/repo.git
Github同时提供了一个图形化界面来替代上面的操做。这和教程中其它工做流设置中央仓库的流程彻底一致。若是有必要的话,项目维护者应该将已有的代码库推送到这个仓库中。
接下来,全部开发者须要fork官方仓库。你能够用SSH到服务器,运行git clone
将它复制到服务器的另外一个地址——fork其实只是服务端的clone。但一样地,Github上开发者只需点一点按钮就能够fork仓库。
在这步以后,每一个开发者应该都有了本身的服务端仓库。像官方仓库同样,全部这些仓库都应该是裸仓库。
接下来开发者须要克隆他们本身的公开仓库。他们能够用熟悉的git clone
命令来完成这一步。
咱们的栗子假设使用他们使用Github来托管仓库。记住,在这种状况下,每一个开发者应该有他们本身的Github帐号,应该用下面的命令克隆服务端仓库:
git clone https://user@github.com/user/repo.git
而教程中的其余工做流使用单一的origin
远程链接,指向中央仓库,Fork工做流须要两个远程链接,一个是中央仓库,另外一个是开发者我的的服务端仓库。你能够给这些远端取任何名字,约定的作法是将origin
做为你fork后的仓库的远端(运行git clone
是会自动建立)和upstream
做为官方项目。
git remote add upstream https://github.com/maintainer/repo
你须要使用上面的命令来建立上游仓库的远程链接。它使得你轻易地保持本地仓库和官方仓库的进展同步。注意若是你的上游仓库开启了认证(好比它没有开源),你须要提供一个用户名,就像这样:
git remote add upstream https://user@bitbucket.org/maintainer/repo.git
它须要用户从官方代码库克隆或拉取以前提供有效的密码。
在他们刚克隆的本地仓库中,开发者能够编辑代码、提交更改,和其它分支中同样建立分支:
git checkout -b some-feature # 编辑代码 git commit -a -m "Add first draft of some feature"
他们全部的更改在推送到公开仓库以前都是彻底私有的。并且,若是官方项目已经向前进展了,他们能够用git pull
获取新的提交:
git pull upstream master
由于开发者应该在专门的功能分支开发,这通常会产生一个快速向前的合并。
一旦开发者准备好共享他们的新功能,他们须要作两件事情。第一,他们必须将贡献的代码推送到本身的公开仓库,让其余开发者可以访问到。他们的origin
远端应该已经设置好了,因此他们只须要:
git push origin feature-branch
这和其余工做流不一样之处在于,origin
远端指向开发者我的的服务端仓库,而不是主代码库。
第二,他们须要通知项目维护者,他们想要将功能并入官方代码库。Github提供了一个“New Pull Request”按钮,跳转到一个网页,让你指明想要并入主仓库的分支。通常来讲,你但愿将功能分支并入上游远端的master
分支。
当项目维护者收到pull request时,他们的工做是决定是否将它并入官方的代码库。他们可使用下面两种方式之一:
第一个选项更简单,让维护者查看修改先后的差别,在上面评论,而后经过图形界面执行合并。然而,若是pull request会致使合并冲突,第二个选项就有了必要。在这个状况中,维护者须要从开发者的服务端仓库fetch功能分支,合并到他们本地的master
分支,而后解决冲突:
git fetch https://bitbucket.org/user/repo feature-branch # 检查修改 git checkout master git merge FETCH_HEAD
一旦修改被整合进本地的master
,维护者须要将它推送到服务器上的官方仓库,这样其余开发者也能够访问它:
git push origin master
记住,维护者的origin
指向他们的公开仓库,也就是项目的官方代码库。开发者的贡献如今彻底并入了项目。
由于主代码库已经取得了新的进展,其余开发者应该和官方仓库同步:
git pull upstream master
若是你从SVN迁移而来,Fork工做流看上去是一个比较大的转变。但不要惧怕——它只是在Feature分支工做流之上引入了一层抽象。贡献的代码发布到开发者在服务端本身的仓库,而不是在惟一的中央仓库中直接共享分支。
这篇文章解释了一次代码贡献是如何从一个开发者流入官方的master
分支的,但相同的方法能够用在将代码贡献整合进任何仓库。好比,若是你团队的一部分红员在一个特定功能上协做,他们能够用本身约定的行为共享修改——而不改变主仓库。
这使得Fork工做流对于松散的团队来讲是个很是强大的工具。任何开发者均可以垂手可得地和其余开发者共享修改,任何分支都能高效地并入主代码库。