用开源软件打造企业级 DevOps 工做流(二):版本控制

前言

本文章为系列文章的第二篇,以前已经写了一篇 《用开源软件打造企业级 DevOps 工做流(一):概述》,主要介绍了DevOps的基本概念以及一些组成要素。在这篇文章中,咱们将介绍 版本控制系统 / VCS(Version Control System),除了介绍版本控制的基础概念之外,咱们还将介绍如何使用开源的 GitLab 来实现版本控制系统。git

版本控制系统

版本控制系统主要是针对软件开发过程当中对代码变动的管理,保证了代码的可回溯、可审查、可管理等功能需求,而最终的目的,是可维护性。在上一篇文章中,咱们举例阐述了没有版本管理工具会出现什么问题,所以不会在本文赘述。其实主要问题就是没有版本管理工具致使的可维护性的降低,从而致使各类不可预测的bug的出现。docker

版本的主要内容包括三部分:数据库

  1. 检入检出控制(Check-In / Check-Out Control)浏览器

  2. 分支与合并(Branch / Merge)bash

  3. 历史记录(History)服务器

检入检出控制

关于检入检出,咱们能够理解为代码与 版本控制系统数据库(VCS Database) 的同步与交互过程(以下图)。网络

检出(Check-out) 至关于用户将 版本控制系统数据库(VCS Database) 的代码同步了一份到本地,若是与本地代码发生了冲突,会比对本地代码并作相应处理(后面咱们会讨论合并)。ssh

检入(Check-in) 至关因而检出的逆操做,也就是将本地代码同步到远端版本管理系统,实际上是对代码数据库的一种更新,至关于一次升级,所以,VCS 须要对将要更新的代码进行版本审查,并会拒绝将不合法的代码升级(例如非最新升级)更新到数据库中。分布式

检入检出的设置保证了代码数据库的原子操做,不会由于两我的同时提交代码而形成冲突。更改代码一般在本地进行,每一次更改完毕后会将最新的代码提交到代码数据库,同时更新代码仓库,保证远端代码是最新的。工具

分支与合并

代码的 分支(Branch) 概念是指同一“祖先“的代码在不一样的方向上各自进行更迭,互不干扰。不一样分支的代码通过不断的迭代,虽然来自同一个“祖先”节点,但极可能演变成彻底不一样的功能和结构。

一个分支至关因而对某个节点的拷贝,同时也能够本身发展成新的版本。版本控制系统中有分支的概念是为了方便开发多个 功能(Feature) 时防止互相干扰,是一种解决代码冲突的方式。

例如,某开发团队须要开发 功能 A功能 B ,而这两个功能都须要在 文件 M 上进行修改。若是同时开发 功能 A功能 B,则会很难协调,由于开发人员须要同时操做文件 M。这就跟要求两个猴子吃同一根香蕉同样困难,那么咱们为何不分红两根香蕉、一只猴吃一根呢?

所以,咱们建立了两个分支 AB,两个开发者分别开发,互不影响,互不干扰,这样操做不会形成代码冲突,开发起来很是和谐。

虽然咱们解决了同时修改一个文件的问题,咱们还须要将两个开发好的功能整合起来,这就产生了 合并(Merge) 的概念。

如上面那张图,当 A 功能B 功能 都开发好了以后,分别为版本 A2 和版本 B2,须要将二者整合在一块儿,产生新的版本 M2,这个整合的过程就是合并。

固然,合并的过程会产生 冲突(Conflict),也就是两个分支同时修改了同一份代码。通常的版本控制系统(例如 GitSVN)会尝试自动将代码进行合并,例如很是明显的增删操做。然而,也有不能自动合并的状况,一般要求开发人员手动合并代码,这叫 解决冲突(Resolve Conflict)

开发过程当中,咱们的分支管理会有不少种策略,通常开发团队会根据项目的须要和团队的状况选择合适的分支管理策略,这个后面会讲。

历史记录

这个其实很好理解,代码的全部变更,变更了什么(What)、何处变动的(Where)、什么时候变的(When)、由谁提交的变动(Who)、为何变动(Why,提交注释),这些都会体如今 历史记录(History) 中。

若是代码出了问题、或者须要参考历史功能等,开发者能够根据历史记录来回溯代码,找到 Bug 发生的缘由,以及理解历史代码的设计等等。这有助于帮助后续的开(jie)发(pan)者(xia)更加轻松地掌握须要管理的代码。

分支管理策略

咱们在前面着重介绍了一下分支与合并,这里咱们会介绍一下其衍生出来的分支管理策略,这对平常开发来讲很是重要,由于不一样的分支策略对项目开发来讲有着深远的影响。

分支管理策略能够看做是一种开发模式:团队成员之间如何经过分支与合并操做来协同工做,将不一样的功能整合在一块儿,开发测试环境如何隔离,生产环境上线后如何作相应更改等等。

下面咱们将介绍几种常见的分支管理策略。

主干开发(Trunk Based Development)

主干开发(Trunk Based Development) 简称为 TBD,是一种常见的分支管理策略,也是 Google 和 Facebook 等大型互联网巨头常常采用的策略之一。

主干开发要求全部代码都提交到 主干(Master) 分支上,从而避免了开发者们看到的代码是过期代码的状况。只有当须要 发布(Release) 的时候,主干才建立一个当前节点的分支,做为发布用。

对于主干开发来讲,开发者要求天天开发前都同步最新代码,若是有与新提交代码的冲突,须要在本地本身解决后从新提交到主干上。这样的好处在于,因为开发者的本地代码基本是跟主干同步的,所以合并时并不会有重大的变动,合并代码的时候相对比较容易,不会花不少时间。

而这样作的缺点也很明显,若是不少人在项目上进行开发,会致使源源不断的更新代码提交到主干,这会致使发布的时候存在众多提交而致使出现了 bug 难以追溯,进而难以修复,容易出现“一颗耗子屎坏了一锅粥”的状况。

咱们接下来要介绍的 Git Flow 分支管理策略就是来解决这个缺点的。

Git Flow

Git Flow 是一种 特性分支(Feature Branch) 策略。特性分支策略的概念跟主干开发策略的概念是相对的,意思是不一样的功能拉出一个分支单独开发,开发好后再合并到主干,保证功能之间互不影响和干扰。

Git Flow 是特性分支策略的一种,是 Vincent Driessen 在 《A Successful Git Branching Model》(nvie.com/posts/a-suc…) 中提出的一种分支模型(以下图)。

简单来讲,Git Flow 要求有 Master(主干)、Develop(开发)、Release(发布)和 Hotfix(热修复)几个基础分支。

每次须要开发新功能时,在 Develop 分支下拉出一个 Feature 分支(特性分支)来进行单独开发,开发好后合并到 Develop 分支。当 Develop 分支开发到必定程度的时候,再将其合并到 Release 分支。

Release 分支是在生产环境的 Master 分支前的起 UAT 测试缓冲做用的预备分支。当 Release 分支准备好以后,就将其合并入 Master 主干分支,这样就至关于在生产环境上发布了新版本了。

当线上版本出了 Bug 须要修复的时候,咱们会在直接在 Master 分支上拉出一个 Hotfix 分支,在这个分支上直接作修复,而后合并回主干。同时 Hotfix 上的几回修复还会合并到 Develop 上的某个节点,以保存此次修复,这样 DevelopMaster 就基本保持了一致。

这是经典意义的 Git Flow,但在实际操做的时候咱们并不必定会原封不动地彻底照搬这个模式。例如,不少时候咱们其实用不到 Release 分支,只存在 MasterDevelop,这对于中小型项目来讲比较灵活。有时候 Release 也被称为 Test 测试分支。另外还有些变种,例如主干开发与 Git Flow 的部分结合,在 Develop 分支上作主干开发,每次须要部署到生产环境的时候就将其合并入 ReleaseMaster 分支,以发布正式版本。

Git or SVN?

GitSVN(Subversion) 是两个比较受欢迎的版本控制工具。二者之间最大的区别是:SVN 是集中式的,而 Git 是分布式的(以下图)。

SVN 要求代码仓库只有一个中心仓库,全部开发者在作提交代码的操做前,必须保证本身本地代码与中心仓库的代码彻底同步;而 Git 相对来讲就灵活得多,Git 不要求全部开发者的本地代码彻底一致,在提交时只要求被 push 的仓库分支与本地的一致就能够。

另外,SVN 的分支合并复杂且不健壮,由于 SVN 没法区分合并是人工操做仍是自动合并的,所以将不会建立一个合并记录节点;而 Git 则相反,会在合并后建立一个合并记录节点,这增长了可回溯性。并且,用 Git 建立分支的成本很低,只须要 git branch <branch_name> 就能够了。

因为分支合并的复杂性,SVN 一般不适合用做特性分支策略,而适合主干开发模式(Google App Engine 就是 SVN 管理的)。

而 Git 则既适合主干开发模式,又天生支持特性分支策略。因此,咱们通常都采用更灵活的 Git 做为版本控制工具,Git 也是如今更为主流的选择。

开源工具 GitLab

GitLab 简介

GitLab 是一个开源的版本控制系统,使用 Git 做为代码管理工具,并在此基础上搭建了 Web 服务,它有着精美的 Web UI 界面,方便用户操做使用。

GitLab 是用 Ruby 编写的开源项目,有很是自由的 MIT 版权,容许二次开发并投入商业使用。

GitLab 支持 Git 代码仓库、权限管理、合并请求、Issues、Wiki、CI/CD 等很是多的强大功能。

GitLab 很是相似 GitHub,支持代码仓库、代码合并、代码审核等基础功能,区别在于:GitHub 是一款云端产品,并且项目大多为开源项目(私有仓库有限制);而 GitLab 是开源产品,能够很是轻松的部署在任意一台服务器上。

咱们用 GitLab 做为咱们 DevOps 工做流的缘由主要在其强大的可视化界面和权限管理,至关于增强版的 Git 仓库。由于人是视觉动物,可视化以后能够更加高效的处理各类复杂信息,GitLab 能够帮助咱们作到可视化操做。

而对于企业开发来讲,一般会有管理多个项目的需求,不一样的项目也会有不一样的开发者参与进来,所以有效地管理这些权限会是个须要注意的问题,而 GitLab 自己就支持相关的权限管理。

安装 GitLab

安装 GitLab 很是简单,咱们推荐的方式是用容器化工具 Docker 来进行安装。若是您对 Docker 不熟悉,能够去网上查找一下相关资料(我相信会很是多),或者关注本系列即将介绍的 DevOps 容器篇,在这篇文章中,咱们将着重介绍 Docker。

在安装以前,确保您已经在本机或者服务器上安装了 Docker,可以执行基本的 Docker 操做,例如docker ps

sudo docker run --detach \ # --detach 表示是后台运行
  --hostname gitlab.example.com \ # GitLab 中引用的 hostname,须要设置为服务器域名
  --publish 443:443 --publish 80:80 --publish 22:22 \ # 映射端口
  --name gitlab \ # 容器名称
  --restart always \ # 容器挂了以后会自动重启
  --volume /srv/gitlab/config:/etc/gitlab \ # 配置持久化
  --volume /srv/gitlab/logs:/var/log/gitlab \ # 日志持久化
  --volume /srv/gitlab/data:/var/opt/gitlab \ # 数据持久化
  gitlab/gitlab-ce:latest # 镜像名称
复制代码

这是官方文档中的 Docker 启动命令,只须要在命令行中输入以上命令,就能够启动 GitLab 了。

稍微等待几十秒,在浏览器中输入 http://localhost 就能够看到 GitLab 的登录页面了。

使用 GitLab

这里咱们不打算详细介绍 GitLab 的全部功能,咱们只会简单介绍 DevOps 工做流中的重要部分,主要是 Git 的版本控制部分:克隆仓库、建立分支、合并分支。剩下的功能交给读者阅读官方文档或者本身安装体验。

克隆仓库

在代码项目中,复制下面 SSH 或者 HTTP 的地址,例如 ssh://localhost/user/project1 ,在本地命令行中输入以下内容。

git clone ssh://localhost/user/project1
复制代码

而后会在当前目录建立一个该项目的目录,并将文件从远端拷贝下来。这里会建立一个originremote记录。能够经过以下方式看到。

git remote -v
复制代码

若是咱们经过 merge request 的方式来进行版本控制管理,咱们将还会用到 git remote 的操做。

建立分支

咱们能够在界面中建立分支,但咱们也能够在本地建立。

在本地项目中输入以下内容建立 develop 分支。

git branch develop
git checkout develop

# or

git checkout -b develop
复制代码

而后更改一些代码,并经过git commit提交代码。接下来,将代码推送到远端服务器。

git push origin develop
复制代码

这样,远端就建立了一个 develop 分支,而且将本地 develop 分支上的commits更新到服务器上了。

合并分支

当咱们想经过合并的方式将 develop 的更新同步到主干 master 分支时,咱们须要合并操做。

在本地,能够这样操做。

git checkout master
git merge develop
git push origin master
复制代码

这样就完成了主干的合并。

然而,有些时候特别是比较大型的项目时,咱们并不但愿在 master 分支上进行修改,咱们想强制要求经过合并代码的方式来更新主干分支。所以,咱们须要加一个保护操做。咱们能够在项目中的 Settings -> Repository -> Protected Branch 中设置保护主干分支,也就是说,不容许 pushmaster (读者请自行了解如何设置,这里不赘述)。

若是作了这样的保护限制,咱们须要经过 merge request 的方式来合并分支。在 GitLab 中的项目首页,点击左侧菜单的 Merge Requests,点击 New merge request,选择 Source branchdevelopTarget branchmaster,点击 Compare branches and continue,进入提交合并请求页面。在这个页面中,你能够看到一些合并信息,包括此次合并有哪些 commits,哪些代码有更改、更改了什么,等等。点击 Submit merge request,一个 merge request 就建立好了。而后,若是你是有权限的角色的话,你能够在这个合并请求页面中点击 Merge 赞成此次请求,master 分支也就合并好了。

GitLab 在合并分支时加入的代码审阅功能对于 Code Review 来讲很是方便。一般来讲有权限赞成合并请求的开发者都是 Reviewer,须要在合并以前审阅提交的代码,并根据审阅的结果赞成或拒绝合并请求。

总结

本篇文章主要介绍了版本控制系统的主要概念,包括检入检出、分支合并、历史记录,以及两种分支开发策略(主干开发和 Git Flow),还比较了 Git 和 SVN。另外,本文还着重介绍了开源版本控制系统 GitLab,介绍了其概念、安装和基本使用。这些知识,对于咱们后面讲 DevOps 工做流是很是重要的基础。下一篇,咱们将介绍持续集成(CI),这与版本控制系统息息相关,由于诸如 Jenkins 或者 GitLab CI/CD 能够用 GitLab 代码仓库做为源码来源来自动构建产品。没有版本控制系统,CI 的优点会受到局限。所以,版本控制系统是 DevOps 工做流中很是重要的模块。

在后面的文章中,咱们将继续介绍 DevOp 的其余内容,包括持续集成、容器化、编排、网络、以及如何将这一切串联起来协同组成企业级的 DevOps 工做流。敬请期待后面的内容。

相关文章
相关标签/搜索