热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

git学习------>Git分支管理最佳实践

ps:本文转载于:https:www.ibm.comdeveloperworkscnjavaj-lo-git-mangeindex.htmlGit是目前最流行的源代码管理工具。大量

ps:本文转载于 : https://www.ibm.com/developerworks/cn/java/j-lo-git-mange/index.html


Git 是目前最流行的源代码管理工具。大量的软件项目由 GitHub、Bitbucket 和 GitLab 这样的云服务平台或是私有的 Git 仓库来管理。在使用 Git 时通常会遇到的一个问题是采用何种分支管理实践,即如何管理仓库中作用不同的各类分支。和软件开发中的其他实践一样,Git 分支管理并没有普遍适用的最佳做法,而只有对每个团队和项目而言最适合的做法。简单来说,在项目开发中使用多个分支会带来额外的管理和维护开销,但是多个分支对于项目的团队合作、新功能开发和发布管理都是有一定好处的。不同的团队可以根据团队人员组成和意愿、项目的发布周期等因素选择最适合的策略,找到最适合团队的管理方式。本文将介绍三种常见的 Git 分支管理方式。

单主干

单主干的分支实践(Trunk-based development,TBD)在 SVN 中比较流行。Google 和 Facebook 都使用这种方式。trunk 是 SVN 中主干分支的名称,对应到 Git 中则是 master 分支。TBD 的特点是所有团队成员都在单个主干分支上进行开发。当需要发布时,先考虑使用标签(tag),即 tag 某个 commit 来作为发布的版本。如果仅靠 tag 不能满足要求,则从主干分支创建发布分支。bug 修复在主干分支中进行,再 cherry-pick 到发布分支。图 1 是 TBD 中分支流程的示意图。

图 1. TBD 中的分支流程的示意图
图 1. TBD 中的分支流程的示意图

由于所有开发人员都在同一个分支上工作,团队需要合理的分工和充分的沟通来保证不同开发人员的代码尽可能少的发生冲突。持续集成和自动化测试是必要的,用来及时发现主干分支中的 bug。因为主干分支是所有开发人员公用的,一个开发人员引入的 bug 可能对其他很多人造成影响。不过好处是由于分支所带来的额外开销非常小。开发人员不需要频繁在不同的分支之间切换。

GitHub flow

GitHub flow 是 GitHub 所使用的一种简单的流程。该流程只使用两类分支,并依托于 GitHub 的 pull request 功能。在 GitHub flow 中,master 分支中包含稳定的代码。该分支已经或即将被部署到生产环境。master 分支的作用是提供一个稳定可靠的代码基础。任何开发人员都不允许把未测试或未审查的代码直接提交到 master 分支。

对代码的任何修改,包括 bug 修复、hotfix、新功能开发等都在单独的分支中进行。不管是一行代码的小改动,还是需要几个星期开发的新功能,都采用同样的方式来管理。当需要进行修改时,从 master 分支创建一个新的分支。新分支的名称应该简单清晰地描述该分支的作用。所有相关的代码修改都在新分支中进行。开发人员可以自由地提交代码和 push 到远程仓库。

当新分支中的代码全部完成之后,通过 GitHub 提交一个新的 pull request。团队中的其他人员会对代码进行审查,提出相关的修改意见。由持续集成服务器(如 Jenkins)对新分支进行自动化测试。当代码通过自动化测试和代码审查之后,该分支的代码被合并到 master 分支。再从 master 分支部署到生产环境。图 2 是 GitHub flow 分支流程的示意图。

图 2. Github flow 中的分支流程的示意图
图 2. Github flow 中的分支流程的示意图

GitHub flow 的好处在于非常简单实用。开发人员需要注意的事项非常少,很容易形成习惯。当需要进行任何修改时,总是从 master 分支创建新分支。完成之后通过 pull request 和相关的代码审查来合并回 master 分支。GitHub flow 要求项目有完善的自动化测试、持续集成和部署等相关的基础设施。每个新分支都需要测试和部署,如果这些不能自动化进行,会增加开发人员的工作量,导致无法有效地实施该流程。这种分支实践也要求团队有代码审查的相应流程。

git-flow

git-flow 应该是目前流传最广的 Git 分支管理实践。git-flow 围绕的核心概念是版本发布(release)。因此 git-flow 适用于有较长版本发布周期的项目。虽然目前推崇的做法是持续集成和随时发布。有的项目甚至可以一天发布很多次。随时发布对于 SaaS 服务类的项目来说是很适合的。不过仍然有很大数量的项目的发布周期是几个星期甚至几个月。较长的发布周期可能是由于非技术相关的因素造成的,比如人员限制、管理层决策和市场营销策略等。

git-flow 流程中包含 5 类分支,分别是 master、develop、新功能分支(feature)、发布分支(release)和 hotfix。这些分支的作用和生命周期各不相同。master 分支中包含的是可以部署到生产环境中的代码,这一点和 GitHub flow 是相同的。develop 分支中包含的是下个版本需要发布的内容。从某种意义上来说,develop 是一个进行代码集成的分支。当 develop 分支集成了足够的新功能和 bug 修复代码之后,通过一个发布流程来完成新版本的发布。发布完成之后,develop 分支的代码会被合并到 master 分支中。

其余三类分支的描述如表 1所示。这三类分支只在需要时从 develop 或 master 分支创建。在完成之后合并到 develop 或 master 分支。合并完成之后该分支被删除。这几类分支的名称应该遵循一定的命名规范,以方便开发人员识别。

表 1. git-flow 分支类型

对于开发过程中的不同任务,需要在对应的分支上进行工作并正确地进行合并。每个任务开始前需要按照指定的步骤完成分支的创建。例如当需要开发一个新的功能时,基本的流程如下:

  • 从 develop 分支创建一个新的 feature 分支,如 feature/my-awesome-feature。
  • 在该 feature 分支上进行开发,提交代码,push 到远端仓库。
  • 当代码完成之后,合并到 develop 分支并删除当前 feature 分支。

在进行版本发布和 hotfix 时也有类似的流程。当需要发布新版本时,采用的是如下的流程:

  • 从 develop 分支创建一个新的 release 分支,如 release/1.4。
  • 把 release 分支部署到持续集成服务器上进行测试。测试包括自动化集成测试和手动的用户接受测试。
  • 对于测试中发现的问题,直接在 release 分支上提交修改。完成修改之后再次部署和测试。
  • 当 release 分支中的代码通过测试之后,把 release 分支合并到 develop 和 master 分支,并在 master 分支上添加相应的 tag。

因为 git-flow 相关的流程比较繁琐和难以记忆,在实践中一般使用辅助脚本来完成相关的工作。比如同样的开发新功能的任务,可以使用 git flow feature start my-awesome-feature 来完成新分支的创建,使用 git flow feature finish my-awesome-feature 来结束 feature 分支。辅助脚本会完成正确的分支创建、切换和合并等工作。

Maven JGit-Flow

对于使用 Apache Maven 的项目来说,Atlassian 的 JGit-Flow 是一个更好的 git-flow 实现。JGit-Flow 是一个基于 JGit 的纯 Java 实现的 git-flow,并不需要安装额外的脚本,只需要作为 Maven 的插件添加到 Maven 项目中即可。JGit-Flow 同时可以替代 Maven release 插件来进行发布管理。JGit-Flow 会负责正确的设置不同分支中的 Maven 项目的 POM 文件中的版本,这对于 Maven 项目的构建和发布是很重要的。

在 Maven 项目的 pom.xml 文件中添加代码清单1中的插件声明就可以使用 JGit-Flow。中包含的是 JGit-Flow 不同任务的配置。

清单 1. JGit-Flow 的 Maven 设置
123456789101112131415161718 <build>   <plugins>       <plugin>           <groupId>external.atlassian.jgitflowgroupId>           <artifactId>jgitflow-maven-pluginartifactId>           <version>1.0-m5.1version>           <configuration>              <flowInitContext>                <versionTagPrefix>release-versionTagPrefix>              flowInitContext>               <releaseBranchVersionSuffix>RCreleaseBranchVersionSuffix>               <noDeploy>truenoDeploy>               <allowSnapshots>trueallowSnapshots>               <allowUntracked>trueallowUntracked>           configuration>       plugin>   plugins>build>

JGit-Flow 提供了很多配置选项,可以在 POM 文件中声明。这些配置项可以对不同的任务生效。常用的配置项如表2 所示。

表 2. JGit-Flow 的配置项

其余的配置项可以参考插件不同任务的文档。

在启用了 JGit-Flow 之后,可以通过 mvn 运行 jgitflow:feature-start 和 jgitflow:feature-finish 来开始和结束新特性的开发。与版本发布和 hotfix 相关的命令分别是 jgitflow:release-start 和 jgitflow:release-finish 以及 jgitflow:hotfix-start 和 jgitflow:hotfix-finish。在运行命令之后,JGit-Flow 会完成相关的 Git 分支创建、合并、删除、添加 tag 等操作,不需要开发人员手动完成。

每个分支的 pom.xml 中的版本号的格式并不相同。如 master 分支的版本号是标准的发布版本号,如 1.2.3;develop 分支中则是 SNAPSHOT 版本,比 master 分支的版本号要高,如 1.2.4-SNAPSHOT;release 分支可以通过配置来指定版本号的后缀,如 1.2.3-RC-SNAPSHOT;feature 分支可以通过配置来把 feature 分支名称作为后缀添加到版本号中,如 1.2.3-my-awesome-feature-SNAPSHOT;hotfix 分支的版本号基于 master 分支的版本号,如 1.2.3.1 是对于 1.2.3 版本的第一个 hotfix。当使用 jgitflow:release-finish 完成一个 release 分支时,develop 分支的版本号会被自动更新成下一个小版本,如从 1.2.3 到 1.2.4。当需要手动修改版本号时,可以使用 Versions 插件,如 mvn versions:set -DnewVersion=2.0.0-SNAPSHOT。

持续集成

由于 JGit-Flow 是纯 Java 的 Maven 插件实现,可以很容易的与常用的持续集成服务器进行集成。不过在与 Atlassian 的 Bamboo 集成时,有几个细节需要注意。首先是 Bamboo 在进行构建的时候,使用的是一个虚拟的 Git 仓库,其仓库地址是一个不存在的文件系统路径。因此需要在 JGit-Flow 的配置中手动设置 Git 仓库的地址,保证 Git 操作可以正确执行,如代码清单2所示。

清单 2. 手动设置 JGit-Flow 的 Git 仓库地址
1234 <configuration>   <defaultOriginUrl>[Git url]defaultOriginUrl>   <alwaysUpdateOrigin>truealwaysUpdateOrigin>configuration>

另外在开始新的 release 之前,需要确保前一个发布分支已经被删除。JGit-Flow 在默认情况下会自动在发布完成之后,删除对应的 Git 分支。但是可能本地仓库中还保留有之前的发布分支,这会导致新的 release-start 任务执行失败。一种解决方式是每次都重新 checkout 新的仓库,这样可以保证不会出现已经在远程被删除的分支。不过可能会增加构建的时间。另外一种解决方式是通过 Git 命令来删除本地分支,如代码清单3所示。

清单 3. 删除 Git 本地分支
12345678 ${bamboo.capability.system.git.executable} fetch --prune --verbose ${bamboo.capability.system.git.executable} branch -vv | awk '/: gone]/{print $1}' |                       xargs ${bamboo.capability.system.git.executable} branch -d 2> /dev/null echo 'stale branches deleted' Git 分支合并冲突处理

当把发布分支合并到 develop 时,可能会出现冲突。因为在发布分支中有与 bug fix 相关的改动,在 develop 分支中有可能修改相同的文件。当有冲突时,直接运行 JGit-Flow 的 release-finish 任务会出错。这个时候需要开发人员手动把发布分支合并到 develop 分支,并解决相应的冲突。然后再次运行 release-finish 任务即可。

选择合适的实践

每个开发团队都应该根据团队自身和项目的特点来选择最适合的分支实践。首先是项目的版本发布周期。如果发布周期较长,则 git-flow 是最好的选择。git-flow 可以很好地解决新功能开发、版本发布、生产系统维护等问题;如果发布周期较短,则 TBD 和 GitHub flow 都是不错的选择。GitHub flow 的特色在于集成了 pull request 和代码审查。如果项目已经使用 GitHub,则 GitHub flow 是最佳的选择。GitHub flow 和 TBD 对持续集成和自动化测试等基础设施有比较高的要求。如果相关的基础设施不完善,则不建议使用。

小结

Git 作为目前最流行的源代码管理工具,已经被很多开发人员所熟悉和使用。在基于 Git 的团队开发中,Git 分支的作用非常重要,可以让团队的不同成员同时在多个相对独立的特性上工作。本文对目前流行的 3 种 Git 分支管理实践做了介绍,并着重介绍了 git-flow 以及与之相关的 Maven JGit-Flow 插件。

相关主题

  • 了解 Google 和 Facebook 的单主干实践。
  • 了解 GitHub flow 的更多内容。
  • 了解 git-flow 的更多内容。
  • 了解 Maven JGit-Flow 插件的更多内容。
  • developerWorks Java 技术专区:这里有数百篇关于 Java 编程各个方面的文章。


推荐阅读
  • Hadoop源码解析1Hadoop工程包架构解析
    1 Hadoop中各工程包依赖简述   Google的核心竞争技术是它的计算平台。Google的大牛们用了下面5篇文章,介绍了它们的计算设施。   GoogleCluster:ht ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文介绍了一些Java开发项目管理工具及其配置教程,包括团队协同工具worktil,版本管理工具GitLab,自动化构建工具Jenkins,项目管理工具Maven和Maven私服Nexus,以及Mybatis的安装和代码自动生成工具。提供了相关链接供读者参考。 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • Java 11相对于Java 8,OptaPlanner性能提升有多大?
    本文通过基准测试比较了Java 11和Java 8对OptaPlanner的性能提升。测试结果表明,在相同的硬件环境下,Java 11相对于Java 8在垃圾回收方面表现更好,从而提升了OptaPlanner的性能。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • 本文介绍了使用Python编写购物程序的实现步骤和代码示例。程序启动后,用户需要输入工资,并打印商品列表。用户可以根据商品编号选择购买商品,程序会检测余额是否充足,如果充足则直接扣款,否则提醒用户。用户可以随时退出程序,在退出时打印已购买商品的数量和余额。附带了完整的代码示例。 ... [详细]
  • 用Vue实现的Demo商品管理效果图及实现代码
    本文介绍了一个使用Vue实现的Demo商品管理的效果图及实现代码。 ... [详细]
  • React 小白初入门
    推荐学习:React官方文档:https:react.docschina.orgReact菜鸟教程:https:www.runoob.c ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
author-avatar
双语的家_352
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有