发布系统Git使用指南

——the Git Way to Use Git

背景

​ 有文章曾归纳,Git是一套内容寻址文件系统,意思是,Git的核心是存储键值对[1]。显然,这样的形式不利于普通人类使用。

通常情况下我们使用的Git命令,都被称作高级命令(例如pull、merge等),区别于底层的低级命令,两种命令分别对应于Git文档中出现Porcelain、Plumbing(第一次在文档见到这些词有没有很困惑!)。

高级命令大都有易读参数与翔实输出,可以认为是由低级命令封装,方便人使用。那么低级命令存在的意义是?

根据文档的描述[2],低级命令的接口相较高级命令,更加稳定。低级指令本身就是为脚本使用而存在的,便于确切的输入参数并精准的识别输出。那么,在发布系统中合理使用低级命令替代高级命令,无疑将会使设计的逻辑更加准确的执行。

以下,根据工作中发布系统的实际场景和经验,从两个方面总结一下如何利用更恰当的Git命令,实现较完备的代码操作流程。

获取代码

代码获取的大致逻辑分为四个层级:确定仓库、确定分支、确定Commit ID、确定目录

仓库

确定仓库地址之前,首先需要当前工作目录是否是一个Git仓库

chentairan@localhost ~/t/git-learn> git rev-parse --is-inside-work-tree
true

​ 确认当前工作目录的仓库地址

chentairan@localhost ~/t/git-learn> git config --list|grep -F "remote.origin.url"
remote.origin.url=ssh://git@gitlab.xxx/chentairan/git-learn.git

​ 如果需要直接设置仓库地址

chentairan@localhost ~/t/git-learn> git config remote.origin.url ssh://git@gitlab.xxx/chentairan/git-learn.git

分支

​ 获取指定远程分支

chentairan@localhost ~/t/git-learn> git fetch ssh://git@gitlab.xxx/chentairan/git-learn.git $BRANCH_NAME:refs/remotes/origin/$BRANCH_NAME
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From ssh://gitlab.xxx/chentairan/git-learn
* [new branch] dev -> origin/dev

​ 获取分支的Commit ID

chentairan@localhost ~/t/git-learn> git rev-parse --verify refs/remotes/origin/$BRANCH_NAME
9e100c01201678286db5d266b8d342b0dd8a8e0d

​ 检出提交

chentairan@localhost ~/t/git-learn> git checkout -f 9e100c01201678286db5d266b8d342b0dd8a8e0d

​ 去掉多余文件

chentairan@localhost ~/t/git-learn> git clean -fdx

多分支集成

​ 在同时有多个RD一起开发的项目中,总会遇到有多个分支需要同时上线的情况(对应多个需求或者同一需求的不同工作部分)。通常的做法是从主干上拉出一个临时分支,将各开发分支的变更全部合并

chentairan@localhost ~/t/git-temp> git fetch origin master:refs/remotes/origin/master $BRANCH_DEV1:refs/remotes/origin/$BRANCH_DEV1 $BRANCH_DEV2:refs/remotes/origin/$BRANCH_DEV2
...
chentairan@localhost ~/t/git-temp> git checkout origin/master
chentairan@localhost ~/t/git-temp> git merge --no-edit --strategy=octopus origin/$BRANCH_DEV1 origin/$BRANCH_DEV2 ...

​ 如果没有冲突,那么多分支的检出就完成了

Commit ID

​ 如果发布时需要检出某指定提交,而不是某分支的最新提交(比如生产环境发布的代码,一定要是测试环境测试通过的代码版本),那么在fetch远程分支之后,直接检出对应提交

chentairan@localhost ~/t/git-temp> git checkout -f $COMMIT_ID

目录

​ 需要集成的项目代码可能不在项目根目录,而在项目下某一目录中,在使用pushd $TARGET_DIRECTORY之后,可能需要检查当前所在目录

chentairan@localhost ~/t/git-temp> pushd target_dir
chentairan@localhost ~/t/git-temp> git rev-parse --show-prefix
target_dir/
chentairan@localhost ~/t/git-temp> popd
chentairan@localhost ~/t/git-temp> git rev-parse --show-prefix chentairan@localhost ~/t/git-temp>

本节回顾

git rev-parse用于查看参数,返回结果通常可以直接使用不需额外处理

git config用于配置、查看参数,绕过了git remote命令可能存在的报错

git fetch用于拉取分支,并不改变当前工作区内容,相比git pull更加精确有效

git checkout用于检出提交,但对于缓存区文件(也许上次集成生成的问题)以及.gitignore中配置的文件不做处理

git clean用于清理工作区,仅留下指定提交下面关联的文件

git merge --no-edit --strategy=octopus用于合并多个分支,--no-edit参数使得CommitMessage不需要编辑,octopus是默认的Merge策略,在遇到复杂合并操作,需要人工解决时,拒绝合并

代码基线

​ 基线管理简单说就两件事:确保开发代码包含代码主干的最新提交,确保代码主干有稳定版本可追溯。再说细一点:发布时检查代码是否合并了主干的最新提交,也即是最新的上线代码;线上发布完成之后,代码合并至主干,并打Tag。

检查代码合并主干

​ 检查是否合并了主干最新提交,通常有两种实现方式:一是在开发提交代码时,Git通过Hook配置检查;二是在发布系统这里,发布前做检查。方法一后续会写一篇文章专门讲Hook的能干的事情,本文主要介绍方法二。

​ 查看代码主干位置

chentairan@localhost ~/t/git-temp> git ls-remote origin refs/heads/master
1297bb993557e8b58b37abc3dbb315402f95f349 refs/heads/master

​ 查看开发代码是否包含此次提交历史

chentairan@localhost ~/t/git-temp> git rev-list $COMMIT_ID
......
f19d66e5a154e3b7415b36d55d6cdd9c3648261d
9e100c01201678286db5d266b8d342b0dd8a8e0d
1297bb993557e8b58b37abc3dbb315402f95f349
......

​ 此处可以通过grep检查是否包含主干的最新提交

向主干合并&Tag

​ 由于开发的代码包含了主干的最新提交,那么向主干合并时,只是一个向前走的过程,一定不会有冲突,所以直接使用merge进行合并

...如第一部分拉取发布分支...
chentairan@localhost ~/t/git-temp> git checkout origin/master
chentairan@localhost ~/t/git-temp> git merge $COMMIT_ID --no-ff -m "$SOME_MESSAGE"
chentairan@localhost ~/t/git-temp> git tag $TAG_INFO -m "Create production tag"
chentairan@localhost ~/t/git-temp> git push origin HEAD:refs/heads/master --tags

本节回顾

git ls-remote用于查看远程代码仓库上主干分支的位置

git rev-list用于查看某次提交之前的历史

git merge --no-ff 用于合并代码。根据健康的Git工作流,所有的开发提交合并至主干时都是fast-forward过程。--no-ff参数能使fast-forward也产生一个新的Merge Commit(无此参数则不会),目的是保持开发分支的开发记录,保持整个代码开发历史的完整性

git tag用于新建Tag,保存线上稳定版本

git push origin HEAD:refs/heads/master --tags用于提交Merge后的代码及Tag。使用origin/master拉取代码,并使用HEAD:refs/heads/master方式提交,相比切换至本地master分支再更新、合并、提交,步骤更简单,并绕过本地master分支可能存在的需要处理的变更

提示&总结

​ 发布系统的准确性直接影响线上稳定性,准确性的首要任务是确保异常产物无法上线

​ 所有的命令均可以通过Shell的$?进行判错,有异常一定终止流程,人工介入,尽量避免使用--force参数

​ 所有的命令以准确性为首要目标,脚本中所有的Git指令,能尽可能全面地指定参数,则尽量全面(曾经遇到过使用Git关键字作为分支名,导致的异常问题,Git偶尔会混淆在命令中该参数的具体含义指代。PS:不规范的名字可以在提交前通过Hook进行检查)

参考文献

[1]https://git-scm.com/book/zh/v1/Git-%E5%86%85%E9%83%A8%E5%8E%9F%E7%90%86-Git-%E5%AF%B9%E8%B1%A1

[2] http://man7.org/linux/man-pages/man1/git.1.html

发布系统Git使用指南 - the Git Way to Use Git的更多相关文章

  1. Git权威指南学习笔记(二)Git暂存区

    例如以下图所看到的: 左側为工作区,是我们的工作文件夹. 右側为版本号库,当中: index标记的是暂存区(stage),所处文件夹为.git/index,记录了文件的状态和变更信息. master标 ...

  2. git——简易指南

    Git对于我来说,只知道是一个版本控制器,类似于乌龟的svn.其中也仅仅会几个常的命令,比如说“更新git pull”.“提交git push”等等,因为记得当初使用的时候,师傅告诉我,对于你不懂这个 ...

  3. 【运维工具】Git代码发布系统

    引言 代码发布系统是互联网公司必备的运维系统,作用主要用户发布业务代码 到 业务服务器 为什么需要代码发布系统 有的同学可能说,我们公司服务器就那么一台,做个发布系统太麻烦了? 不认同这说法 发布系统 ...

  4. git 行动指南

    Git是一个分布式的版本管理工具. 在本地项目和服务器都会拥有版本库,本地版本库由自己控制,自由选择提交代码到服务器端 windows上也建议使用命令的方式来使用git,推荐使用客户端 :http:/ ...

  5. 【转】git - 简明指南

    git - 简明指南 助你入门 git 的简明指南,木有高深内容 ;) 作者:罗杰·杜德勒 感谢:@tfnico, @fhd 和 Namics其他语言 english, deutsch, españo ...

  6. Git 进阶指南(git ssh keys / reset / rebase / alias / tag / submodule )

    在掌握了基础的 Git 使用 之后,可能会遇到一些常见的问题.以下是猫哥筛选总结的部分常见问题,分享给各位朋友,掌握了这些问题的中的要点之后,git 进阶也就完成了,它包含以下部分: 如何修改 ori ...

  7. Git权威指南 书摘

    ##$ git add welcome.txtwarning: LF will be replaced by CRLF in welcome.txt.The file will have its or ...

  8. Git 进阶指南

    转自: https://github.com/kaiye/kaiye.github.com/issues/7 在掌握了基础的 Git 使用 之后,可能会遇到一些问题.以下是猫哥筛选总结的部分常见问题, ...

  9. 我总结的git命令指南。

    git命令行指南 1.windows上安装git的网址:http://msysgit.github.com/. 没有安装过git的 这个网址里下mymsgit. 因为发现有些同学对git还不是那么熟悉 ...

随机推荐

  1. WeTest+微信:小程序云端测试系统上线

    日前,微信新增小程序测试系统,可便于开发者检测小程序缺陷,评估小程序产品质量.在小程序发布之前,开发者可将小程序代码提交到测试系统,在不同型号的手机真机上运行,执行完毕后自动生成测试报告.小程序云端测 ...

  2. 团队作业10--事后分析(Beta版本)

    设想和目标 1. 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件的作用是帮助用户实现准确快速的电子文档查重,我们对软件的定义是电子文档查重系统,即通过文 ...

  3. 2015211230554《Java程序设计》第6周学习总结

    1. 本周学习总结 2. 书面作业 1.1 Object对象中的clone方法是被protected修饰,在自定义的类中覆盖clone方法时需要注意什么? 克隆方法用于创建对象的拷贝,为了使用clon ...

  4. 201521123008<java程序设计>第三周实验总结

    1.本周学习总结 2.书面作业 1.代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; pub ...

  5. Java课程设计 ————五子棋 (个人博客)

    JAVA课程设计 五子棋(博客个人版) •团队课程设计博客链接 http://www.cnblogs.com/mz201521044152/p/7065575.html •个人负责模块或任务说明 1. ...

  6. Eclipse rap 富客户端开发总结(5): RAP国际化之路

    Eclipse RCP 中的plugin.xml国际化实现 1.  在工程的根目录下面建立一个plugin.properties资源文件:在此资源文件中写入需要国际化的内容(键/值对),举例如下: h ...

  7. idea使用转载【别人的专栏】

    维C果糖

  8. [13] static 和 final

    不论是类.属性,还是方法的声明中,都有一个可设置的"修饰符",它可以实现一些高级特性. 1.static static被称之为静态的,并不是指不可以修改的意思,而是说它的内存空间是 ...

  9. [android游戏开发初学]简单的游戏框架

    这两天,没事想学习游戏开发,看了一些资料之后准备开始.为了将来编码方便,先写了一个简单的游戏框架方便自己以后做练习用. 如果以后没有什么特殊的需求--比如opengl什么的,会尽量用这个简单框架来实现 ...

  10. js学习要点

    js 一.词法结构 1.区分大小写 2.注意 // 单行 /* 多行注释 */ 3.字面量(直接量 literal) 12 //数字 5.8 // 小数 "hello" 'hell ...