Git 的十年变化(五)|学习笔记

简介: 快速学习 Git 的十年变化(五)。

开发者学堂课程【Git 从入门到进阶Git 的十年变化(五)】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/1194/detail/18119


Git 的十年变化(五)


内容介绍:

一、 Clone卡顿问题

二、 Git远端通讯

三、 Git fetch/pull/clone交互

四、 Git push交互

五、 总结

 

一、clone问题

通过前面几期学习,想必大家已经对 Git 有了一定的了解,并且已经开始使用Git了,接下来给大家介绍一下 Git 的交互协议。

通过这节课,希望大家能够简单快速的了解 Git 是如何以服务器进行通讯的。当在clone 一个仓库的时候,大家有没有碰到过 Git 会卡住的情况?

image.png

Git 会一直显示正在 clone……然后就没有任何信息了,这时大家可能会去猜想给它是出了什么问题吗?我是否需要 QC掉重新 clone呢?正当大家纠结的时候,可以看到 Git 已经 clone 完毕了。

image.png

大家有了解,Git 为什么会卡住这几秒呢?来带大家看一下Git究竟在做什么?通过trace 来看一下 Git 交互通信的协议。协议的过程。

需要再跟命令之前开启 Git trees 开关,并且将日志输出到文件中。开始 clone。

看一下日志文件可以看到 deal 分支以及 master 分支正常的传送过来了,但随之而来的是非常多的 require 非常非常多。

image.png

直接翻到日志的最后面,可以看到,最终才发送完毕,然后才开始发送客户端的一些信息,以及最后服务器给客户端的一些详细信息。

image.png

在最前面,可以看到 deal 分支以及 master 分支之还有其它分支,这些分支称之为前期的引用发现问题也就一目了然了:

 image.png

原来是因为服务器端发送了大量的引用发现信息。但这些用信息客户端并不完全需要。

因为给的客户端只关注两部分内容,一部分是以 *refs/heads/* 为开头的代表服务器上的引用信息,还有 *refs/tags/*代表服务器上的标签信息,对于 ribs/merge-requests 为前缀的这些分支,一般是代码托管平台上的 PR 分支。

随着的分支增多,这种分支会越来越多,在 clone的时候也会越来越慢。继续看一下Git 是如何远端进行通讯的。


二、 Git远端通讯

通过一个客人与掌柜的一个交易过程,来给大家展示一下 Git 的通讯方式,将给的用户想象成是一个客人。将阿里云 codeup 或者是 Github 想象成是一个掌柜。

image.png

来看一下 Git 在协议当中是如何进行通讯的。在刚开始客人会对掌柜的说我来买东西了,掌柜收到后会将自己所有的商品清单罗列下来交给客人。

image.png

清单中就包含了 iPhone 系列、iPad 系列、华为手机系列。当客人收到这些清单之后,客人就开始发送它的自己的需求。比如客人会说想要 iPhone,但我不想要IPhone14。掌柜收到信息后,会对 iPhone14是有所疑虑的, 因为掌柜这里是没有iPhone14,所以它会给客人回复这里没有 iPhone14,要不要确认一下呢?

image.png

客人原来是弄错了,其实是不想要 iPhone11和更老的版本。这时掌柜收到了最终的信息之后,还要再确认一下,你确定吗?还有别的需求吗?这时客人会告诉掌柜没有了。然后掌柜的就开始对它现有的 iPhone的手机进行打包,这时 Git 的协议的交互就结束了。

继续看一下 Git 在协议二当中又是如何通讯的。在开始的时候,掌柜开始张罗自己正在卖东西,然后会说新店开业,欢迎光临,甚至会去说新店有哪些服务,比如本店14天无理由退货。

image.png

这时客人,会直接的向掌柜问道,你家有 iPhone吗?

image.png

掌柜的会直接回复,我家全系列的 iPhone都有,包括最新的 iPhone13。这时候客人会直接发送真正的需求,比如会告诉掌柜的,我只要 iPhone12和iPhone13 iPhone11和之前的版本都不要。

image.png

掌柜的收到信息后就会直接开始打包发送,协议二、协议一,最大的区别是什么?是掌柜的并不需要将所有的产品清单罗列出来,而是由客人来指定,就如刚刚视频上来说是由客人直接问掌柜的要 iPhone 的一些信息,而不需要掌柜罗列 iPad 以及华为手机在罗列出来给客户。对于前面讲的协议,如果用协议二,*refs/heads/*开头的ribs/merge-requests 就不会再发送,这种简单的卡住的这种情况可能会有一些减缓。


三、Git fetch/pull/clone交互

接下来看一下 Git 真正的协议与刚刚看到的小动画的一些对应关系,先看一条比较特殊的引用,这条引引用是在协议当中,这条引用的刚开头,可以看到是由一个哈希和一个 HEAD 放在一起,J代表 head 所指向的一个提交,在中间我们可以看到一个 -0,这信息在字节里,它就是一个 null 字符,它是用来做分割的,后面剩下一些非常多的内容,在当中也添加了省略号,对于这些内容,是 Git 或者客户端、服务端所支持的 capability 能力。

image.png

继续看一下协议。

image.png

对于第一条,可以看到前两条的信息,相当于掌柜的开始给客人发送商品清单,以及它所支持的能力,这里边就会包括 iPhone 系列,iPad 系列,华为手机系列,当客人收到清单后,客人会发送它的需求,比如想要 iPhone,这时候它会发送的请求,对于iphone11以及 iphone11更老的版本,购物是已经有了,所以它会告诉掌柜的不需要这些,给掌柜的发送 help 请求。

image.png

掌柜的收到了这些需求之后,会做一些确认,确认这些我都有,然后最终没问题,之后掌柜的就开始打包这些手机信息。并且把状态发送给了客户。

image.png

对于协议二,它与我们之前的动画的对应关系是这样的:协议二和协议一是有一些区别的,刚刚有了解到,协议二它并不会先将所有的用发现发送,而是先会发送服务器的 capability,也就是能力。然后对于引用一些信息,就不会混合到一起,这样会更清晰一些。刚开始的时候会发送自己的能力,一些信息,就相当于掌柜的会去说小店开业,欢迎光临,以及小店支持的能力,比如是14天无理由退货、免费送货等服务。这时客人收到了小店开业之类的信息之后,它会直接去告诉掌柜的它的需求,比如掌柜想问一下有没有 iPhone系列。

image.png

掌柜的收到之后,会直接告诉客人,iPhone 系列都有。这时客人就会发送它具体的需求。

比如只想要 iPhone系列,但 iphone11以及 iPhone11之前的版本我都有了,不需要了。这时候掌柜就会发送明白,iPhone12 iPhone13我都有,然后掌柜就直接开始打包,并最后发送了状态的信息给客户。

image.png


四、Git push交互

在 Git push 交互时,和之前讲的那些其它的操作是有一些不同,因为在 Git push 过程中,它仅仅只支持第一,所以就缺少了之前讲的沟通环节,比如会给掌柜的发送需求 help 或者是 want 之类,在 push 当中是没有的,来看一下 push 的过程,对应的小动画在push的刚开始,是由客人直接会告诉掌柜的说你那里有什么样的货,可以让我看一下吗?

image.png

然后,掌柜的就直接在继续罗列清单,然后比如有 iPhone系列,iPad 系列,华为手机系列,并且对于前面这一小节和之前讲的协议是完全一样的。这里客户看到掌柜的清单当中并没有 iPhone14,这时客人就直接将 iPhone14推销给了掌柜。

image.png

对于掌柜来说,它有两种选择,一种就是接受 iPhone14,另一种是不接受,对于接受,就是掌柜会觉得你很厉害,你既然能搞到,我收下了,对于不接受的场景,掌柜的会告诉不接受的原因,比如苹果公司都没有出 iPhone14,你怎么可能会有,一定是山寨的,我不要我不收。

对于push来说,Get push 会直接根据服务器发送的引擎发现来快速找到 base 提交,以此来发送增量包,base 提交其实就是它们的公共提交,但如果没有找到 base 提交,push 就会将本地所有的对象进行打包和发送,因为之前所讲到的fetch/pull/clone的相比,它缺少了相互沟通,这还真的就是推就完了。

 

五、总结

接下来来给大家总结一下之前讲的一些关键点,对于 clone 为什么会卡住呢?是因为服务器要处理以及发送大量的引用发现,导致前面讲的 fetch/pull/clone,也就是客户端之间与服务器如何协商以及沟通。通过了小动画进行了讲述,紧接着又讲述了一下 Protocol v2的通讯以及交互是如何的跑到 v2,它会首先发送 capability,并且不在与引用发现混合在一起,最后客户端会要求服务器。只发送 *refs/heads/* 为开头,还有 *refs/tags/* 分支对于 push 来说,Push 只需要一种发现,然后直接就推送,没有任何协商。

看一个小问题,在 push 过程中是因为没有协商的,所以可能在某种情况下,仅通过引用发现无法找到准确的公共提交。因此在向服务端推送数据的时候,可能会产生有余强制推送的时候,甚至会将仓库所有的数据已经重新打包一起发送,应该要怎么解决问题呢?

Git 在最近出了一项新的功能。功能就是 push.negotiate,现在来给大家制造一个强制推送,会打包所有对象的一个场景,然后再添加上 push 的格式选项,来看一下前后的效果。首先来 push 一个仓库,看到它是冲突了,需要强制推送,然后强制推送一下。可以发现它发送了大量的内容。大约发送了100多兆,有30多万的对象。重置一下被推送的仓库,然后再重新强制推送一次。

image.png

在强制推送的时候,使用 push.negotiate 新的选项,把它设置为 true,再推一遍,大家可以看到推送完毕。只发送了三个对象以及13KB大小的对象数据。

image.png

通过小实例可以看到,通过使用 push.negotiate,push的性能大大提高。

原因是因为将配置设置为 true 的时候,就会开启服务器的协商的逻辑,在使用push的过程中,会执行 Git fetch 等相关的操作,去通过协商找到了公共提交,只需要发送增量包就可,就会开启与服务器的协商的逻辑,在使用 push 的过程中,它会执行 Git fetch 相关的操作,去通过协商来找到公共的提交,找到了公共提交,只需要发送增量包就可以了,以此来提升 Git push 的效率,对于 push.negotiate 也是有前置条件的。版本是必须得是二,三以上并且,服务器需要广播 wait-for- down capability,最后,就是对于所使用的代码托管服务,Gitlab 是支持的。

Github 暂时没有支持,接下来阿里云以及其它的厂商会陆续去支持,后续大家就可以方便地快速地启用参数来提升push效率。

相关文章
|
3月前
|
Shell 网络安全 开发工具
Git学习笔记
Git学习笔记
79 1
Git学习笔记
|
7月前
|
Linux 网络安全 开发工具
Git学习笔记
Git学习笔记
56 0
|
8月前
|
Linux 网络安全 API
git常用命令学习笔记
git常用命令学习笔记
45 0
|
9月前
|
程序员 开发工具 git
搭建博客可能会用到的 Git 命令|学习笔记
搭建博客可能会用到的 Git 命令|学习笔记
|
10月前
|
算法 安全 Linux
git第n次学习笔记
git第n次学习笔记
71 0
|
12月前
|
项目管理 开发工具 git
Git学习笔记(三) git submodule
Git学习笔记(三) git submodule
124 0
|
12月前
|
缓存 开发工具 git
Git学习笔记(二) git stash
Git学习笔记(二) git stash
848 0
|
12月前
|
开发工具 git
Git学习笔记(一) 常用命令
Git学习笔记(一) 常用命令
104 0
|
12月前
|
缓存 Linux 程序员
【学习笔记之Linux】工具之make/Makefile与git
【学习笔记之Linux】工具之make/Makefile与git
172 0
|
开发工具 git 索引
Git学习笔记-详细使用教程
Git学习笔记-详细使用教程
Git学习笔记-详细使用教程

相关实验场景

更多