一切皆代码。
工作中的任何材料,包括代码、产品手册、配置。 这些代码的编写离不开历史的逐步修改和多人协作完成。版本管理工具作为团队的基础工具,就是用于对代码进行管理,用于存储,最终源代码文件的修改历史,并为团队提供多端共享的代码协作。
哪些是源代码
一切皆代码,在IT企业中,重要的开发信息包括:
- 项目的源代码,如Java、PHP、HTML等通过各种程序语言编写的应用程序源代码
- 服务器配置。包括服务器系统中的软件管理、编译属性, 也包括项目在运行时使用的配置文件,同时也应包含文件服务器、防火墙等配置等
- 项目文档。包括产品需求、分析文档、设计文档、项目手册、产品手册等。
这些内容,都应作为源代码存储至代码仓库。在DevOps中,源代码管理系统是我们的重要的中心节点。DevOps运行时的信息,都应来自于GIT。
哪些不建议放入代码仓库
可以方便的重新获取或生成的内容,不宜放入代码仓库, 如:
- 从互联网下载的二进制包。如tomcat,nginx等应用程序。源代码仓库中只需保存这些应用程序的版本号信息。通过脚本或手动下载的方式,获得改版本号的二进制包。
- 应用程序的编译结果或中间过程。包括编译生成的.a, .jar等目标文件。
- 业务报表数据。
- 已在其他仓库中的代码。不应该将同一分代码在多个仓库中进行存储。应使用Submodule或者其他方式,进行连接,而不是简单复制。
选择版本管理系统
GIT是最流行的源代码管理系统。其他经典的版本管理软件还包括CVS和Subversion。
安装GIT客户端
GIT支持所有平台安装和使用。
在Linux上安装
可使用基础软件包管理工具进行,如yum、apt-get。
$ sudo yum install git-all #Fedora,CentOS等
$ sudo apt-get install git-all #Debian发行版
在Mac机器上
最简单的方法是安装 Xcode Command Line Tools 。
在Windows上安装
在GIT官方网站下载windows版本,链接地址:https://git-scm.com/download/win。 下载后,双击exe文件根据指引进行安装。
安装图形界面
GIT命令行对于日常工作已经足够了,而且足够的快捷、方便,强烈推荐开发者直接使用命令行进行熟练操作。当需要进行冲突处理,历史回溯工作时,图形界面是一个不错的辅助工具。推荐的图形工具包括:
- Github客户端。GITHUB官方客户端,与GITHUB项目集成非常方便。界面漂亮友好,对源代码高亮支持、查阅提交历史非常方便。缺点是不便于冲突处理。
- Source Tree。Source Tree内置支持Git Flow,能非常方便的查看和处理分支,包括分支的切换和合并。与Github形成非常好的互补。
TortoiseGit。 Windows专用,适合于原本在Windows下使用TortoiseSVN的开发人员。
在集成开发中,也包含了一些好用的工具, 如Eclipse中内置的egit等。
建立GIT中心仓库
GIT在技术上是去中心化的,但定义一个中心仓库,能够更方便团队开发人员快速的使用Git并进行协作。
- 使用云端GIT服务平台
国际最为流行的是 GITHUB.com。GITHUB对开源项目免费。私有项目中每账户需付费9美金/月。国内用户可以使用 Coding.net,根据代码参与者规模不同,价格从免费到2000人民币不等。
本书各章节的源代码,放置在GITHUB上。以免费开源的形式,供读者参考查阅。
- 企业内部自建GIT服务器
相当多的公司不希望其代码离开企业内部环境,因此自建GIT服务器是其最佳选择。开源的GIT服务器项目有GitLab,GitWeb,Gitosis以及Gitolite。其中,Gitlab的功能更全面一些。
通过命令行安装GITLAB
以CentOS 7为例通过包管理工具进行安装,其他的版本可以参考gitlab官方安装文档:
https://about.gitlab.com/downloads/
curl -shttps://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh| sudo bash
sudo yum install gitlab-ce
sudo gitlab-ctl reconfigure
服务启动后可通过 http://127.0.0.1/ 访问。在gitlab界面中,使用初始用户名root,默认密码 5iveL!fe 登录,并修改密码。至此gitlab的安装就全部完成了。
通过Docker安装GITLAB
更简单的,我们可以通过docker来安装gitlab服务。关于docker的介绍,将在本书后面章节介绍。
docker run --detach \
--hostname gitlab.luochunhui.com \
--publish 8443:443 --publish 8080:80 --publish 8022:22 \
--name gitlab-ce \
--restart always \
--volume /data/gitlab/config:/etc/gitlab \
--volume /data/gitlab/logs:/var/log/gitlab \
--volume /data/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest
安装成功后,使用浏览器打开http://localhost:8080/访问。和命令行安装GITLAB不同,这个页面直接进入密码修改功能。
通过自动化部署脚本安装GITLAB
通过自动化部署脚本,我们可以很快速的将gitlab安装至指定的机器上。我们使用的工具是ansible,相关介绍将在第N章进行,
> ansible-galaxy install gikoluo.gitlab
> vi 31-gitlab.yml
---
- name: Install Gitlab
hosts: "gitlab"
roles:
- role: gikoluo.gitlab
gitlab_external_url: "https://gitlab.example.com/"
gitlab_smtp_enable: true
gitlab_smtp_address: "smtp.qq.com"
gitlab_smtp_port: 465
gitlab_smtp_user_name: "[email protected]"
gitlab_smtp_password: "smtp password"
gitlab_smtp_domain: ""
> vi hosts
[gitlab]
10.100.18.106
> ansible-playbook 31-gitlab.yml
建立GIT用户和登录凭证
- 使用管理员root账户登录到Gitlab后,点击 右上角 Admin Area, 然后在上方找到 Users 标签,进入用户管理页面
- 点击『New User』, 填入Name(用户姓名或昵称),Username(登录用户名),Email,点击保存,完成用户创建。
- 用户的邮箱将收到一份来自gitlab的邮件,用户可根据指引,完成密码设置,并登录。
- 如果gitlab的邮箱还无法正常工作,则管理员可以编辑用户信息,手动设置一个新密码后,告知开发者进行登录。

在用户使用git之前,需要先将SSH Key导入到gitlab中。
- 开发人员在工作电脑上,使用SSH KEY工具,生成id_rsa.pub文件,在终端命令行中输入一下指令(Windows用户打开Git Bash输入指令):
> # ssh-keygen -t rsa -b 4096 -C "[email protected]"
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/Luo/.ssh/id_rsa):
Created directory '/Users/Luo/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /Users/Luo/.ssh/id_rsa.
Your public key has been saved in /Users/Luo/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:eJBn6LxopvALtHGaYmr+XRlut7o+/1cE0L6jsu0HiLo [email protected]
The key's randomart image is:
+---[RSA 4096]——+
+----[SHA256]-----+
运行后,系统会询问几个问题,一路敲回车即可。完成后将生成公私钥文件。其中公钥文件以pub为后缀,文件内容是以ssh-rsa开头的单行文件。
- 开发人员使用在前文完成注册的账户密码,登录到gitlab系统中,点击右上角头像,选择User Settings,选择SSH Keys。然后把公钥id_rsa.pub文件内容复制到key输入框内。点击Add Key保存。
创建GIT项目
开发人员登录到gitlab后,找到『New Project』,即可进入项目新建流程。建立项目钱,推荐先按照业务或职能团队创建建立组,
点击『New Group』,在Group Path中输入组名,如book。
然后点击『New Project』,在Project Name中填出项目名称,如:devops-practice。
如果这个项目在Github或其他云端GIT服务平台中存在,则可以选择从其他项目中导入功能,按照界面提示导入项目。
点击Create Project,完成项目仓库的创建。
页面将自动跳转至项目指引页面,该页面展示了开发者如何通过客户端获取仓库、提交代码。
提交代码
根据项目指引页面的命令行,我们可以进行代码拉取和提交操作
git clone http://127.0.0.1:8000/book/devops-practice.git
cd devops-practice
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master
分支管理模型
对于小型团队,一般使用master主分支,以及少量的功能分支进行开发。而对于一个项目并行工作较多的协作团队,选择一个好的分支管理策略,能保证组织的高效协作,减少代码冲突。
Git Flow(由Vincent Driessen发布)提供了一个非常优秀的git分支管理模型。充分的适配于团队的日常开发、新功能开发、紧急bug修复。模型约定了开发人员的操作规范,建立对应的处理过程,使得软件的开发过程更易于上线发布流程的管理。
ref: http://nvie.com/posts/a-successful-git-branching-model/
Git Flow模型包括两类分支:
主要分支
主要分支在项目整个生命周期中长期存在。
主分支master:代码库仅有一个主干分支,其最新代码代表着生产环境的发布版本。
开发分支develop:代表着开发人员为下一个发布版本提交的最新代码。有时我们也将其称之为『集成分支』。它一般可用于自动集成工具发布『每日构建』。
当源代码在develop分支中被开发完成,并准备发布时,所有的提交变更都应该被合并至master分支,并使用tag工具标记一个版本号。

辅助分支
辅助分支
用于支持团队成员的并行开发,包括新功能开发、生产发布准备,生产环境的问题修复等。和主要分支不同,辅助分支一般只在需要时被建立,生命周期结束后即被释放删除。
| 说明\分支类型 | 作用 | 分支来源 | 分支合并目标 | 示意图 |
|---|---|---|---|---|
| 新功能分支 | 用于即将开发的或更长期的功能开发 | 开发分支 | 开发分支 | ![]() |
| 发布分支 | 用于新版本发布前的准备工作。它允许我们在发布前,做最后一点点改动,包括少量BUG的修改、元数据(如版本信息、编译参数等)的修改等。 | 开发分支 | 开发分支和主分支 | ![]() |
| 紧急修复分支 | 应用于生产环境中出现的紧急bug修复,防止和开发分支相互影响。 | 主分支 | 主分支和开发分支 | ![]() |
使用分支管理代码
通过GIT flow插件,开发人员可以更容易的使用Git Flow模型。使用代码如下:
ref: http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/
我们以本书将要提到的开源启停服务管理管理工具:Steve为例,来说明Git Flow的集成和使用流程:
- 初始化Git Flow,使其集成至现有项目中。
$ git clone [https://github.com/gikoluo/Steve.git](https://github.com/gikoluo/Steve.git) \#从Github中获得代码
$ cd Steve
$ git flow init \#初始化Git Flow, 系统会进行一些提问,保持默认值一路回车即可。
Initialized empty Git repository in ~/project/.git/
No branches exist yet. Base branches must be created now.
Branch name for production releases: \[master\]
Branch name for "next release" development: \[develop\]
How to name your supporting branch prefixes?
Feature branches? \[feature/\]
Release branches? \[release/\]
Hotfix branches? \[hotfix/\]
Support branches? \[support/\]
Version tag prefix? \[\]
$ git branch \#查看一下当前分支。此时分支已经被切换到develop
\* develop
master
- 开始新功能的开发周期,完成后合并至develop ```
$ git flow feature start systemd_support #开始一个新的开发任务,使得Steve能够支持Systemd服务的维护。
Switched to a new branch 'feature/systemd_support'
Summary of actions:
A new branch 'feature/systemd_support' was created, based on 'develop'
You are now on branch 'feature/systemd_support'
Now, start committing on your feature. When done, use:
git flow feature finish systemd\_support
$ git add README.md “the changed file list for this feathure” #进行功能开发,通过多次的git提交来完成此次功能开发
$ git commit -am "ADD System type instruction”
$ git push --set-upstream origin feature/systemd_support
$ git flow feature finish systemd_support #功能开发结束后,完成此次分支。分支将被删除,其代码被自动合并入develop
Switched to branch 'develop'
Updating adc4972..4b5ea10
Fast-forward
README.md | 3 +++
1 file changed, 3 insertions(+)
Deleted branch feature/systemd_support (was 4b5ea10).
Summary of actions:
The feature branch 'feature/systemd_support' was merged into 'develop'
Feature branch 'feature/systemd_support' has been removed
You are now on branch 'develop'
3. 开始上线过程,完成后发布至master
$ git flow release start 0.9.1 #准备发布,新的版本号为0.9.1
Switched to a new branch 'release/0.9.1'
Summary of actions:
A new branch 'release/0.9.1' was created, based on 'develop'
You are now on branch 'release/0.9.1'
Follow-up actions:
Bump the version number now!
Start committing last-minute fixes in preparing your release
When done, run:
git flow release finish ‘0.9.1'
$ ./bump-version.sh #通过脚本,修改源代码中的版本标识符。
current version is 0.9.1
sa/steve.sh is updated, , STEVE_VERSION=“0.9.1”
$ git add sa/steve.sh && git commit -am "steve version updated” #提交这些修改
$ git flow release finish 0.9.1 #发布工作完成操作,系统会将该分支代码合并至master,标记tag,然后合并并切换至
develop
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 5 commits.
(use "git push" to publish your local commits)
Merge made by the 'recursive' strategy.
sa/steve.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Switched to branch 'develop'
Your branch is ahead of 'origin/develop' by 3 commits.
(use "git push" to publish your local commits)
Merge made by the 'recursive' strategy.
sa/steve.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Deleted branch release/0.9.1 (was db80986).
Summary of actions:
Latest objects have been fetched from 'origin'
Release branch has been merged into 'master'
The release was tagged '0.9.1'
Release branch has been back-merged into 'develop'
Release branch 'release/0.9.1' has been deleted ```
hotfix
flow和新功能流程相似
$ git flow hotfix start assets
$ git flow hotfix finish assets


