g4e基础篇#6 了解Git历史记录
章节目录
1. 基础篇:
- 为什么要使用版本控制系统
- Git 分布式版本控制系统的优势
- Git 安装和设置
- 了解Git存储库(Repo)
- 起步 1 – 创建分支和保存代码
- 起步 2 – 了解Git历史记录
- 起步 3 – 拉取请求 Pull Request 工作机制
Git的版本历史记录采用了与传统集中式版本管理系统完全不同的方式进行组织,在刚开始使用Git的时候我们往往会不知所措,比如看到这样的历史记录。
看到这个七拐八拐的图形,你可能完全不知道它代表了什么。其实这正是Git的特别之处,Git之所以能够实现之前我们所说那些灵活快速的操作,都是因为它采用这种类似链路的版本记录方式。在这一篇中,我们就一起了解一下这个图形是如何生成的。
这里,我们要模拟一个常见的开发场景:
- 你正在开发一个网站的某个新功能,按照Git的推荐方式,你创建了feature1分支来承载这个新功能的代码变更。
- 当你已经在这个功能上完成几次代码提交的时候,你的项目经理告诉你这个网站现在出现了一个严重的线上问题,需要紧急修复。
- 为了能够快速修复这个线上问题,你不能等待下一个版本发布,必须在现有线上版本上进行修复。这时你暂停了feature1分支的开发工作,切换回到master分支,从新拉取一个名为hotfix的分支并在这个分支上开始了线上问题的修复。
- 当你完成了修复并测试通过后,你将hotfix分支合并到master以便立即从新发布线上版本。
- 完成以上工作后,你切换回到feature1分支继续进行新功能的开发直到新的功能也经过测试可以发布。
- 最后你将feature1分支也合并回到master分支,发布到线上环境。
为了演示这个过程,首先我使用 Visual Studio 创建了一个新的Web网站项目,完成了4次提交并推送到了TFS的Git仓库。
初始状态
初始的历史记录显示如下:
用简单的示意图表示,是这样的:
如果使用命令行查看历史记录可以键入如下命令
>>> git log --oneline --graph
以上的–oneline参数让git只输出第一行的注释信息,简化历史记录更加可读;–graph参数用来在命令行中输出图形链路,现在我们还看不到效果,后面就会有变化。
输出的结果如下
注:如果你在使用以上命令的过程中遇到乱码,请参考:常见问题#4
这表示当前的master分支指向版本库最新的一次提交(C4),同时之前的所有提交都是顺序完成的,形成了一个单一主线的链路。在TFS的版本记录视图上你所看到的图形一列表示的是同一个意思。
创建feature1分支并提交2次变更
现在,按照我们在上一篇中介绍的方法,创建feature1分支,并在这上面完成2次新的提交。
此时再次使用上面的命令列出历史记录,你会看到如下结果:
这个时候你就会有点纳闷了,为什么明明做了分支,历史记录仍然是单一的直线呢?不是应该分叉了吗?看一下示意图你就明白了。
Git确实记录了你的分支信息,只不过它非常聪明的只是修改了feature1所指向的提交而已;这时你的master分支仍然指向C4提交,而feature1分支则指向C6提交了。
以上git log所输出的信息中也非常明确的标明了这一点,看一下历史记录的第1行和第3行括号里面内容就明白了。
创建hotfix分支并提交另外2次变更
现在那个讨厌的项目经理给你下达了新的任务,要修复线上问题。因为线上所部署的正是master分支上的最新版本,所以你需要切换到master分支(也就是C4提交所代表的版本)进行修改。
这时你可以使用以下命令完成hotfix分支的创建
>>> git checkout master
>>> git checkout -b hotfix
完成这个操作后,我们在hotfix分支上输出历史记录。
你会看到现在hotfix和master分支同时指向了一个提交记录(C4),示意图如下:
现在我们在hotfix分支上添加2个新的变更,并输出历史记录
现在hotfix所指向的提交变成了 C8,如果再看我们的示意图就可以看到分叉的效果了
但是为什么git 输出的历史记录中仍然是一条直线呢?这是因为对于master, hotfix和feature1任何一个分支而言,他们的改动对于自己都是单向的唯一链路。
合并hotfix分支到master
现在你已经完成了问题修复,可以将代码合并到master并发布到线上环境了,让我们将hotfix分支的代码合并到master主干上。你需要执行下面命令
>>> git checkout master
>>> git merge hotfix
这2条命令的意思是回到master分支并将hotfix分支的改动合并进来,因为hotfix就是基于master分支进行的,所以合并会直接完成不会有任何的冲突出现。
这里出现了一个词Fast-forward,因为hotfix分支是直接在master分支上完成的,所以git其实仅仅修改了master分支的指向到hotfix的当前指向(也就是C8),输出一下log你就看得很清楚了。
对比刚才在hotfix上的log输出,你会看到这里唯一的变化就是本地master分支的指向移动到了最后一条提交上。你也许会注意到这里还有一个origin/master的指向仍然在之前的提交之上,这时因为我们的Git库已经提交到了TFS的中心存储库,而这个origin/master所代表的是这个中心存储库上的master分支所处的位置,因为我们在以上过程中没有给中心存储库推送过代码,所以这个中心存储库的master分支仍然指向的是最初的位置。
到这里你会明白,Git的分支其实就是一个指针而已,通过这个指针对提交的指向,Git可以非常灵活的切换版本。
到了这里,我们的示意图就变成了这个样子了
合并feature1分支到master分支
现在你已经修复了线上问题,可以回到feature1上继续工作了。假设我们提交C9以后feature1的开发工作也已经完成可以合并了。与刚才合并hotfix的方法一样,我们只需要返回master分支并执行合并命令
>>> git checkout master
>>> git merge feature1
执行的效果如下:
现在如果我们再次在master上输出历史记录,你将看到如下效果
你会注意到git创建了一个新的提交 b5bcb0b 并将这个提交的注释设置为 Merge branch ‘feature1’,它的意思是我为你创建了一个新的提交,在这个提交里面保存了feature1合并进来的代码变更。
注意:在执行merge动作的时候出现了3个Auto-merging的信息,这表明Git自动为你完成了3个文件的合并,在实际使用中这样做可能是会出现问题的,因为Git实际上只是根据文件代码行的信息判断是否可以完成自动合并,这种合并并不是永远安全可靠的。这一点我们在进阶篇中会特别介绍。
现在,我们的示意图就变成了这个样子
最后,我们可以同步代码到TFS中心存储库,并查看服务器上的历史记录。你会看到与我们的示意图非常类似的图形显示。
小结
了解Git处理历史记录的方式对于我们用好Git非常重要,特别是在企业级开发中处理复杂的多版本并行开发的过程中。以上我们提到的几个可能令你困惑的地方,比如hotfix分支合并的时候Git仅仅移动指针的行为,以及最后合并feature1分支时Git创建用于合并的提交的方式都是我们在日常开发中常见的情况。理解了Git的特殊处理方式有助于你在遇到类似情况的时候作出正确的判断,并对后面介绍的很多复杂场景更容易理解。
示例代码:
以上示例代码已经推送到 https://github.com/lean-soft/git-history-demo
参考:
相关文章:
- DevOps文档中心的技术实践演进
- 微软研发云全家桶VSTS登陆中国
- Markdown/reST 文档发布流水线
- 几款好用的Git GUI客户端工具
- 使用 SSH 连接 TFS/VSTS 的GIT仓库
- GitHub + VSTS 开源代码双向同步
请关注微信公众号 【devopshub】,获取更多关于DevOps研发运维一体化的信息
g4e基础篇#6 了解Git历史记录的更多相关文章
- g4e基础篇#4 了解Git存储库(Repo)
章节目录 前言 1. 基础篇: 为什么要使用版本控制系统 Git 分布式版本控制系统的优势 Git 安装和设置 了解Git存储库(Repo) 起步 1 – 创建分支和保存代码 起步 2 – 了解Git ...
- g4e基础篇#2 Git分布式版本控制系统的优势
g4e 是 Git for Enterprise Developer的简写,这个系列文章会统一使用g4e作为标识,便于大家查看和搜索. 章节目录 前言 1. 基础篇: 为什么要使用版本控制系统 Git ...
- g4e基础篇#3 Git安装与配置
g4e 是 Git for Enterprise Developer的简写,这个系列文章会统一使用g4e作为标识,便于大家查看和搜索. 章节目录 前言 1. 基础篇: 为什么要使用版本控制系统 Git ...
- g4e基础篇#1 什么是版本控制系统
g4e 是 Git for Enterprise Developer的简写,这个系列文章会统一使用g4e作为标识,便于大家查看和搜索. 章节目录 前言 1. 基础篇: 为什么要使用版本控制系统 Git ...
- g4e基础篇#1 为什么要使用版本控制系统
g4e 是 Git for Enterprise Developer的简写,这个系列文章会统一使用g4e作为标识,便于大家查看和搜索. 章节目录 前言 1. 基础篇: 为什么要使用版本控制系统 Git ...
- g4e基础篇#5 创建分支和保存代码
章节目录 前言 1. 基础篇: 为什么要使用版本控制系统 Git 分布式版本控制系统的优势 Git 安装和设置 了解Git存储库(Repo) 起步 1 – 创建分支和保存代码 起步 2 – 了解Git ...
- Git使用基础篇
Git使用基础篇 前言 Git是一个分布式的版本控制工具,本篇文章从介绍Git开始,重点在于介绍Git的基本命令和使用技巧,让你尝试使用Git的同时,体验到原来一个版 本控制工具可以对开发产生如此之多 ...
- Git使用基础篇(zz)
Git使用基础篇 您的评价: 收藏该经验 Git是一个分布式的版本控制工具,本篇文章从介绍Git开始,重点在于介绍Git的基本命令和使用技巧,让你尝试使用Git的同时,体 ...
- Git操作(基础篇)
Git操作(基础篇) Git是一款免费.开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目.Git的读音为/gɪt/.Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常 ...
随机推荐
- JS 详解 Cookie、 LocalStorage 与 SessionStorage
基本概念 Cookie Cookie 是小甜饼的意思.顾名思义,cookie 确实非常小,它的大小限制为4KB左右.它的主要用途有保存登录信息,比如你登录某个网站市场可以看到"记住密码&qu ...
- File System 之本地文件系统
上一篇文章提到了,最近做一个基于 File System/IndexedDB的应用,上一篇是定额和使用的查询. 因为LocalFileSystem只有chrome支持,有点尴尬,如果按需加载又何来尴尬 ...
- 理解SynchronizationContext,如何在Winform里面跨线程访问UI控件
SynchronizationContext 类是一个基类,可提供不带同步的自由线程上下文. 此类实现的同步模型的目的是使公共语言运行库内部的异步/同步操作能够针对不同的异步模型采取正确的行为.此模型 ...
- PyCharm/WebStorm遇到Cannot start internal HTTP server
在开始学习html.css的时候,使用PyCharm 的模拟链接到服务器的时候总是遇到 网上也没有遇到合适的解决方案,遂下载了WebStorm,希望能通过安装配置好一些设置,结果依然不行,只有从头分析 ...
- [Spark内核] 第37课:Task执行内幕与结果处理解密
本课主题 Task执行内幕与结果处理解密 引言 这一章我们主要关心的是 Task 是怎样被计算的以及结果是怎么被处理的 了解 Task 是怎样被计算的以及结果是怎么被处理的 Task 执行原理流程图 ...
- SpringCloud学习笔记(5)——Config
参考Spring Cloud官方文档第4~10章 官网文档中所有示例中的配置都在git上 https://github.com/spring-cloud-samples/config-repo Par ...
- 教你用.Net来玩微信跳一跳
目前开发的所有代码都已经上传到了GitHub.欢迎大家来Star https://github.com/GiantLiu/AutoJump 目前程序分为“全自动版本”和“半自动版本” 全自动版本 We ...
- 深入设计电子计算器(一)——CPU指令集设计
版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖.如要转贴,必须注明原文网址 http://www.cnblogs.com/Colin-Cai/p/8254096.html 作者:窗户 Q ...
- LeetCode第[1]题(Java):Two Sum 标签:Array
题目: Given an array of integers, return indices of the two numbers such that they add up to a specifi ...
- jq龙禧轮播图
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...