好代码是管出来的——Git的分支工做流与Pull Request

   上一篇文章介绍了经常使用的版本控制工具以及git的基本用法,从基本用法来看git与其它的版本控制工具好像区别不大,都是对代码新增、提交进行管理,能够查看提交历史、代码差别等功能。但实际上git有一个重量级的功能“分支”,git的分支与其它工具的分支不一样,git分支的操做彻底在本地进行,因此能够快速的建立和切换。html

  版本控制工具除了对代码进行管理外,实际上它还影响了整个软件编码的工做流程,git由于其分支特性使得开发流程发生了变化,本文将从如下几点来介绍分支和git的工做流程:git

版本控制管理分支简介

  在使用集中式的版本管理工具时,通常会在项目的仓库中建立Trunk(主干)、Branches(分支)、Tag(标记)几个目录,分别用于放置开发代码、代码分支以及代码里程碑,分支的目的是为了开发一些测试性功能或者修复Bug时从开发主线上分开避免互相影响,可是要注意的是集中式的工具建立分支的过程是由服务器完成的,当服务器完成分支的建立后,使用者还须要将分支代码checkout到本地,若是项目较大或者网络较慢,那么checkout将是一个漫长的过程,因此使用集中式工具时分支的建立是相对谨慎的。
  对于Git来讲分支就是整个仓库的基础(注:当使用git init命令建立一个仓库时,默认会建立一个名为master的分支),因为Git的本地处理特性,分支的建立基本是一瞬间完成的,正由于这一特性,使用git来进行代码开发的工做流程就有了巨大的变化,如开发功能时建立对应的分支、修复bug(不只仅是生产bug,任何测试产生的bug均可以建立分支)以及开源项目任何人均可以建立本身的分支进行开发。程序员

Git的分支

分支的基本操做

  • 查看分支:(git branch)

  

  • 分支的建立:(git branch TranslateMainPage)

  

  • 分支的切换:(git checkout TranslateMainPage)

  

  注:git checkout -b TranslateMainPage至关于执行了建立和切换两个命令。github

  • 分支的合并:(git merge TranslateMainPage)

  

  • 分支的删除:(git branch -d TranslateMainPage)

  

  • 将本地分支上传到远程服务器:(git push -u origin version0  注:-u是--set-upstream的缩写)

  

  

远程分支以其基本操做

  Git的操做都是基于分支的,同时Git做为一个分布式的版本控制工具可使用远程托管平台来进行代码库托管,那Git的分支是如何在远程平台上体现的呢?
  Git中有一个remote命令,它能够用来管理一系列被跟踪或者说被关联的远程仓库(注:remote管理的是仓库),以下图经过git remote以及 git remote show origin来查看远程仓库的信息:服务器

   

  这里要注意的是“origin”,它其实是远程仓库的一个名称,经过容易记忆名称来代替仓库的URL地址更加容易使用,另外若是使用git clone命令来克隆一个远程仓库,那么远程仓库名称会默认为origin。
  对于远程分支经常使用的操做有:网络

  • 添加新的远程仓库:(git remote add Myblog https://github.com/yqszt/Myblog.git,Myblog是本地用来代替后面Url的名称)

  

  • 克隆一个远程仓库:(git clone https://github.com/yqszt/MyBlog.git)

  

  默认建立一个名称为origin的远程仓库:app

  

  • 将数据(commit)提交到远程仓库:(git push origin)

  

  • 从远程仓库拉取更新:(git fetch)

  注:使用git fetch后,并不会将新的内容更新到工做区域的文件中,因此能够经过git diff master origin/master命令来比较差别分布式

  

  同时也可使用git merge命令来将更新合并到工做区域:工具

  

  注:git pull命令至关于执行了git fetch和git merge两个命令。post

Git基于分支的工做流程

  以前提到过集中式版本工具中分支的做用是开发一些测试性功能或者修复一些稳定版本的Bug,使用分支能够与开发主线隔离,当完成后再合并到主线中,这种开发流程被称为“集中式工做流”,它的工做流程可当作:

   

  1. 以主分支Trunk为核心进行开发,换句话就是开发人员把开发代码都提交到Trunk上,提交以前获取全部代码,而且保证代码能编译成功。
  2. 若是有测试性功能,为了与主干代码分离,经过开启分支的形式完成功能开发。(注:这里写测试性功能的缘由是,集中式的版本控制工具开启分支代价相对较大,因此在建立分支的时候是谨慎的)。
  3. 当开发达到一个里程碑时,经过建立Tag分支来保存里程碑状态,同时Tag出现问题时,能够经过建立Bug修复分支或者直接在Tag分支上修复问题,最终将修复代码合并到Trunk上。
  对于分布式的Git来讲,因为它建立和切换分支的代价很小,因此能够频繁的建立和切换分支,而分支的功能就是与主干代码隔离,以致于在开发过程当中不会由于不完善的功能代码致使主干代码被污染,从而致使没法编译经过,它主要有如下几种开发工做流:

集中式工做流

  集中式工做流就是上面提到集中式版本控制工具中经常使用的开发流程,以主分支为核心,全部开发人员经过更新主分支代码完成代码的开发工做,同时也会建立一些分支和标签(Git的默认分支是Master):

  

功能开发工做流

  功能开发工做流程是以功能为单位进行分支建立,其过程以下:

  

  经过建立对应的功能或问题修复分支,完成功能的开发和Bug的修复。这样的好处就是功能与功能之间的代码是隔离的互不影响,利用Git的快速切换分支特性,能够在同一工做目录下同时开发多个功能,且各个功能之间的代码不会互相影响。另外全部新代码均经过合并的方式合并到Master分支,这样代码更容易控制管理。

Gitflow工做流

  Gitflow能够看做是功能开发工做流的完善版本,它除了Master分支、特性分支、Bug修复分支外,还引入了release、develop两个分支来管理发布和开发,而Master只保存稳定版本的代码。

  

  (图片来自http://www.javashuo.com/article/p-fbiyftjh-cc.html
  总的来讲Git就是使用它快速建立和切换分支的特性,在开发过程当中经过分支来完成功能的开发、Bug修复以及代码发布。
  更多信息可参考:http://nvie.com/posts/a-successful-git-branching-model/
          https://blog.csdn.net/wwj_748/article/details/55226044

Git的分布式工做流

  前面介绍了Git的特性之一“分支”的工做流,那么Git的特性之二“分布式”又会对开发模式带来什么样的变化?

再谈集中式工做流

  为何又是集中式工做流?文章前面介绍的集中式工做流主要偏重于“分支”,全部工做的内容提交到一个Trunk或者Master的分支上。
  而这里的集中式工做流是针对与代码仓库来讲的,全部开发人员使用同一个代码仓库进行协同工做,Git中使用集中式工做流时还能够采用特性分支或者Git Flow工做流来体现Git分支带来的便利(注:若是一个项目的贡献者只有一我的的话,实际上集中式工做流联合特性或Git flow来进行开发是最适合的):

  

  在使用集中式版本控制工具时,使用的就是集中式工做流,全部的开发人员共享一个代码仓库,当其中一人提交代码时须要先更新其它人的提交,可能会出现代码冲突须要合并,还有可能会将其它人的提交覆盖掉,同时因为没法保证代码质量,甚至会出现引入了其它开发人员的代码致使编译不经过、测试不经过等等问题,因此在使用集中式工做流程的时候最不能缺乏的就是“沟通”。
  对于开源项目来讲开发人员来自全世界,其沟通成本远远大于本地团队,那么做为开源项目使用最普遍的版本控制工具,它是如何解决协同开发问题?

集成管理者工做流

  Git中能够建立多个仓库,集成管理者工做流的核心就是项目的主仓库由“集成者”负责,其它开发人员拥有本身的仓库,开发者把完成的工做提交到本身的公开库中,而后“集成者”从这些公开库中拉取代码最终合并到主仓库中,以下图:

  

  这样作有如下几个好处:

  • 开发人员有本身的代码库,减小了更新、合并等操做(注:更新、合并的根源在于不一样开发任务之间的依赖,若是依赖严重,那么更新、合并是不可避免的,最理想的状况是没有依赖,那么开发人员只需完成本身的工做提交便可)。
  • 全部代码合并由“集成者”完成合并,而通常“集成者”由经验丰富的程序员担任,代码合并的过程强制进行了代码复审,对于代码的质量是可控的,有效保证主项目代码的干净整洁。
  • 因为代码的复审,开发人员在提交代码时也不会太随意,变相提升了代码质量。

  可是相对于集中式的工做流来讲因为须要等待合并,提交工做也比较复杂,因此开发效率会相对下降。

司令官与副官工做流

  司令官与副官工做流是集成管理者工做流的拓展,引入了多级“集成者”来完成多级的代码合并操做,该模式适用于复杂的多级管理的项目开发:

  

  

  更多关于Git分布式工做流的内容可参考:https://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows

Pull Request

  在Git中不管是集中式工做流仍是集成管理者工做流,它都有一个核心的操做就是合并代码,对于集中式工做流来讲,当分支完成开发后,须要将代码进行合并,通常是将分支代码合并到远程的如Master或Develop之类的长期分支上,其流程以下:
  1. 建立一个功能分支feature1(git checkout -b feature1)。
  2. 在分支上完成功能并提交(git add & git commit)。
  3. 切换到master分支执行合并操做,并将更新推到远程仓库(git checkout master, git merge feature1, git push)。
  4. 删除特性分支(git branch -d feature1)。

  过程以下图所示:

  

  可是对于集成管理者工做流来讲,集成管理者要如何知道有代码须要合并?要如何合并代码?Git中引入了pull request这一功能完全的改变了代码的合并方式,这一特性也让其成为开源专用的版本控制工具。
  pull request是什么?用中文翻译过来是“拉请求”,假设如下场景:
  1. Selim开发了一个应用程序My Blog,并经过某一Git远程托管平台对代码进行了托管。
  2. 7m鱼复制了Selim托管的库,而后在App上添加了一个新功能feature1。
  3. 如今7m鱼想要将新功能合并到Selim的分支上应该如何操做?以下图所示:

   

  首先能够想到的就是使用上面提到的方法切换到Selim的master分支,而后执行git merge Feature1命令,可是若是7m鱼没有Selim/Master的修改权限呢?Selim/Master是属于Selim的,7m鱼没法修改(典型的集成管理者模式,这里“Selim”就是集成管理者),为了解决这个问题Git实现了“Pull Request(拉请求)”,注意是“拉(pull)”不是“推(push)”,这个请求的目的是让仓库全部者来“拉”取变化,由全部者来决定合并仍是拒绝,全部者能够根据功能是否合理、代码是否正确、易读等信息进行判断,这实际上就是CodeRview的过程。
  下面建立一个新的代码仓库来演示Git的Pull Request,Pull Request的要求就是须要两个远程分支(仓库)进行合并(代码拥有者的分支和代码贡献者的分支):
  1. 克隆My Blog代码,建立一个新的远程仓库(本例使用GitHub做为托管平台,能够直接fork):
  git clone https://github.com/yqszt/MyBlog.git
  git remote add other https://github.com/SelimTeam/MyBlog.git
  git push -u other
  新建的远程仓库:

  

  2. 在克隆的代码中修改内容并提交:

  

  3. 要将这两次提交生成“pull request”:
  使用git request-pull命令生成拉请求信息:
  git request-pull -p 5bf2e35 https://github.com/SelimTeam/MyBlog.git master

  

  其中p表明输出详细内容(代码的差别),5bf2e35对应的是提交的hash,表明更新的内容是从哪个提交开始,url表明的是贡献者的仓库地址,最后的master表明更新内容结束的提交,默认是分支的最新提交
  4. 将pull request信息告知做者,做者将会知道贡献者的仓库地址分支从哪个提交开始哪个提交结束,而且带有详细的变动信息
  注:这里的告知是经过邮件等方式将上面request-pull命令生成的信息发送给做者,github等平台上提供的pull request功能是由平台本身实现的通知方式,关于github上的pull request后续介绍。
  5. 做者添加贡献者的远程仓库,获取并将更新合并到主分支:
  git remote add selimteam https://github.com/SelimTeam/MyBlog.git
  git fetch selimteam master
  git diff master selimteam/master

  

  git merge selimteam/master

  

  git push
  以上就完成了一次经过pull request像做者贡献代码的流程。

Git经常使用的GUI工具

  从上一篇文章开始都是介绍如何经过命令行的方式使用Git进行代码管理,但在前面的文章中就提到过Git除了原生的命令模式还有GUI模式,GUI主要是针对Git的命令进行封装而后提供了一些更便利的功能来简化使用、提升开发效率。
  Git中经常使用的GUI工具备如下几种:

  • SourceTree:一个开源的Git GUI工具,有一个重要的点是它提供了对git flow的支持

  

  https://www.sourcetreeapp.com/
  安装参考:http://www.javashuo.com/article/p-kiezokne-br.html

  • GitHub For Desktop:GitHub的GUI客户端,能够经过它直接提交pull request(GitHub的PullRequest)

  

  • Visual Studio:VS在团队资源管理器中集成了Git的支持,能够在修改完成代码后便捷的进行代码的提交、push等操做

  

  Git的GUI工具备不少,能够经过该连接查找:https://git-scm.com/download/gui/win

小结

  本文主要介绍了Git分支和Git的工做流,Git的工做流分为两个方面“分支工做流”和“分布式工做流”,两种工做流是混合在一块儿使用的,前者是用分支对代码进行隔离,后者使用多个远程库以及Pull Request解决了分布式开发、合并的问题。
  文章的最后介绍了经常使用的Git GUI工具,在实际开发中选择适合的GUI工具能够大大的提升开发效率。

参考:
  https://git-scm.com/docs/git-request-pull
  http://www.javashuo.com/article/p-azvbhgty-ee.html
  https://longair.net/blog/2009/04/16/git-fetch-and-merge/
  http://nvie.com/posts/a-successful-git-branching-model/
  http://www.javashuo.com/article/p-fbiyftjh-cc.html
  https://blog.csdn.net/wwj_748/article/details/55226044
  https://stackoverflow.com/questions/4037928/can-you-issue-pull-requests-from-the-command-line-on-github

本文连接:http://www.javashuo.com/article/p-tksnzswt-es.html 

好代码是管出来的——浅谈.Net Core的代码管理方法与落地(更新中...)

相关文章
相关标签/搜索