当前位置:首页 > 公众号精选 > 小林coding
[导读]大家好哇~欢迎来我的神奇的“科普”频道!今天,我们为大家介绍程序员是如何怎么存档并管理文件版本的。大家要做好心理准备,今天的“科普”稍有点点硬核,我想从需求分析,产品设计,代码实现等全方位角度为大家“科普”,综合的东西较多,可能不太好看懂......但内容应该还是有点点意思的,毕...


大家好哇~ 欢迎来我的神奇的“科普”频道!

今天,我们为大家介绍程序员是如何怎么存档并管理文件版本的。
大家要做好心理准备,今天的“科普”稍有点点硬核,我想从需求分析,产品设计,代码实现等全方位角度为大家“科普”,综合的东西较多,可能不太好看懂......
但内容应该还是有点点意思的,毕竟我总是写一些乱七八糟的东西,如果暂时感觉难以消化可以考虑先收藏吖~


在开始之前,我们先为大家介绍一个概念,叫:版本管理。
我们先从日常生活讲起。

阿菌这坏小子有时会想回到自己的过去,比如说回到小学时候的自己,回到初中时的自己,回到高中时的自己,或者回到大学前的自己,重读一次大学等等......

人生的每个阶段,我们都可以看成自己的一个版本,比如说小学版的阿菌,初中版的阿菌,高中版的阿菌,大学版的阿菌......


要是老天真的给我们每个阶段都存了档,那我们就可以回到过去的版本,重新开始了!

从旧版本发展出新的人生,或许我们的人生可以拥有好几条分支路线呢......


虽然目前看来不太现实,就算真的有得选,阿菌也绝不会回到过去的版本,因为阿菌不敢保证在另一条人生分支上,还能遇到波姐......

咳咳,打住!
虽然人生没有存档,但是电脑上的文件可以存档!
大家考虑以下场景:假设学院安排我们做一次毕业晚会宣传活动,既要有 PPT,又要有文稿,还得有海报。

于是我们高高兴兴地把全学院的本科生资料编写到了 PTT,文稿和海报里。


这个时候,学院说:怎么可以只有本科生的资料?研究生的相关资料也要加进去!

然后我们在现有的 PPT,文稿和海报里,加入了研究生的资料。
接着学院说:临时通知,研究生的晚会另外举行!
大家可能就傻眼了:我们已经在 PPT,文稿和海报里加了研究生的信息,而且已经和本科生的内容融合到了一起,这删起来也太麻烦了吧!!!
要是我们提前把本科生的策划资料保存为一个版本就好了,这样就能直接把本科生的版本交给学院,完成工作。

现在场景有了,痛点有了,接下来我们着手设计一款软件产品来解决这个问题(有同学会说,阿菌你扯淡,我每个版本复制一份就行啦,搞个软件出来干嘛?呃呃,坚持看完就懂啦,它不只存档这么简单哦。我们手动拷贝存档容易出现各种各样的问题,比如忘了存,忘了存在哪,存的顺序搞乱了等等......试过就会有体会哦)。
现在我们有一个文件夹,文件夹目录下有 PPT,文稿和海报,要不我们就在这里创建多一个文件夹用于存档吧!把名字起名为“.jun”就好啦!

现在我们创建好了一个“.jun”文件夹用于存放当前目录的版本信息,接下来我们要思考的是,该如何保存各个文件的版本?
在计算机领域,我们来到的环节应该叫设计底层数据结构,我们可以把“.jun”文件夹看成一个数据库,这个数据库会用来保存当前文件夹下文件的版本数据。

嗯,不如这样吧!
我们就把这些.doc、.psd、.ppt文件称为 object 吧!(反正也不知道叫什么好)我们在“.jun”文件夹下创建一个“objects”文件用于存放各个 object 的信息,这样,我们就有了一个 object 数据库了!

呃,听起来好像很厉害,其实阿菌只是创建了两个文件夹......

现在我们想想一个 object 该存些什么东西比较好,究竟什么东西才能精准定位一个文件的版本信息呢?

想来想去,不如这样吧,我们一个 object 至少得包含三个信息:

1.  文件的原本信息,我们PPT,WORD文档中的内容就叫原本信息,直接保存原本信息可能需要很大的空间(至少和这些文件本身一样大),我们可以先压缩,再保存。
2. object 的类型,考虑到我们当前文件夹下除了有 PPT,文稿和海报之外,以后还可能放新的文件或者新的文件夹,文件和文件夹都应该叫 object,只不过可以用不同的类型区分他们。(大家可以在这留个心眼,这是这款版本控制管理软件的精华部分,后面就知道啦)

3. 一串字符数字,我们起个专业点的名字叫哈希值,用于标识当前的 object,每个 object 都有独一无二的哈希值(其实就一串乱七八糟的数字字符,这样不容易重复)。



看到这里,大家可能会有疑惑:你们为啥一直在说怎么设计,我们更想知道的是,为什么这么设计?

下面揭示谜底:
大家先看第一张图,当前文件夹下的 PPT,文稿和海报,我们可以分别用三个 object 表示:

由于他们放在同一个目录下,于是我们可以用一个大的 object 来标记他们,我们把这个大 object 的类型定义为 tree(树干的感觉),这个 tree object 对等的就不是一个个文件了,而是一个文件夹:


细心的读者朋友会发现:咦?这个 tree object 貌似已经包含了当前文件夹下的所有文件信息,也就是说,这个 tree object 貌似已经可以记录当前文件夹的版本信息了!
我们可以通过这个 tree object 找到PPT,文稿和海报对应的 object 们,这些 object 保存有PPT,文稿和海报某个时间点的原信息,我们只要把这些信息解压出来,就能把文件夹恢复到曾经存档时候的样子了。
接下来的问题是:我们不会只保留一份存档,我们会保存很多份存档,如何才能把一系列存档组织起来呢?
接下来我们引入一个新的 object 类型,我们叫起名叫 commit 类型好了,就是一个提交的意思。想要把存档串联起来,我们得加上一项参数,指明上一个 commit object 是谁,或许我们还可以加上时间等信息,这样一来,每一次提交就是一个版本:

上面这个图由于位置不够,画得不够直观,我们再画一个图,大家明白每个 commit object 都指向一个 tree object 就行了。也就是说:commit object 只是 tree object 的一层封装,虽然还原出一个文件夹过去的存档我们只需要 tree object,但封装成了 commit object 后,通过“father”这个属性,就能把一系列的存档连起来,而且还能盖上时间戳,这样整个存档记录就很清晰了。

讲到这里不知道大家会不会冒出一些奇怪的想法,假设学院布下了两个任务:我们本科生,既要和研究生搞一次毕业联谊,又要和博士生搞一次毕业联谊,我们这套版本管理系统还能用上吗?(也只有阿菌才能想出这样奇奇怪怪的活动)
当然可以啦,请看下图:

我们可以创建两个 commit object(两个新的存档),分别指向最开始保存了本科生资料的存档,然后我们就能分别在两个新的存档上干活啦,而且两个存档互不影响,可以继续在两个存档之后建立新的存档,就像下面这样:

我们可以给上面的功能起个好听的名字,叫“分支”。
分支的功能还可以这样用,我们考虑下面这种场景:
学院不再搞花样了,只要做好本科生的毕业活动策划就行。但是学院规定的时间很短,阿菌一个人做不完,他找来了他的同学阿叉和阿勾一起做,三个人分别负责PPT,文稿和海报。
为了不影响最开始的版本,他们三个每人拉出来一条分支进行工作,每个工作阶段的内容照样进行版本管理:

等各自的工作完成后,合并出最新的版本:


这样一来,大家协同工作起来就方便多啦。
可能有同学会问:阿菌,你设计的 commit object 不是有一个父指针么?每个父指针指向上一个 commit object,在上面的图里,最终版的父指针指向谁呀?貌似一共有三个父节点?
呃,这个确实是阿菌疏忽了,图没有画好......



是这样的,有时候我们数据结构设计好了,最好就不要改了,遇到现有数据结构不能掌控的场景,我们就要设计处理流程,这就是所谓的“算法”吧......(毕竟增删改查某种程度也算是算法......)
我们总是说:软件 = 数据结构 算法,下面阿菌带大家还原这个处理流程的设计。

因为我们的 commit object 只能指向一个父节点,于是我们设计的合并流程是这样子的:最终的合并,交给一个人处理(站在一条分支上处理,假设叫它主分支)。


从上图可以看到,我们以阿叉制作PPT的分支作为主分支,把阿勾的分支内容合并到了阿叉的分支上,这样阿叉的分支就多出来一个合并节点,这个合并节点指向的是阿叉分支上的前一个节点,这样一来,PPT 和文稿内容就合并到主分支上了。
滴滴滴~ 下面我们把阿菌那坏小子制作的海报也合并上去:


这样一来,我们既没有破坏原来的数据结构,也没有破坏软件的设计:一个存档版本管理软件,我们可以在阿叉这条主分支上找到所有的内容。
当然阿菌这样的设计不太好,我们其实可以设计得更好,比如说单独抽出来一条主分支,阿叉,阿勾,阿菌制作各自内容的时候单独拉分支(一共四条分支),每个人都制作好了,再合并回主分支。这样主分支就会非常干净利落,而不是像现在这样,在主分支上,还能看到阿叉的各个版本......
呃呃,软件开发就是这样的啦,在摸索中不断总结最佳实践!




估计大家看着看着就能看出来啦:阿菌,你这讲的不是 Git 么?

没错,阿菌今天介绍的就是一款叫 Git 的分布式版本控制软件-版本控制部分的底层设计原理,现在大多数程序员都是基于 Git 进行协同开发的。和上面例子不同的是,程序员写的是代码文件,而不是文稿和PPT。有时候一个功能往往会有好几个程序员开发,大家可以理解为分组开发。常见主流的协作流程会是这样的:


简单介绍一下:
一、master 分支存储了正式发布的历史版本,是一个功能完整且随时可以发布到线上进行部署的可用分支。

二、Hotfix 分支是用来修复线上bug,快速打补丁的。
三、Release 是一个发布分支。
四、Develop 一般作为功能的集成分支。

五、 Feature 分支则是功能分支。
至于每个分支具体的用法,大家可以到网上搜索,根据阿菌的经验,其实看了也没啥用。只有真正到公司里参与到开发项目中,才能真正领会到各个分支的意义。
今天介绍的内容,是 Git 这款软件最基本的原理,在搞清楚了这个的基础上使用 Git,会轻松很多。Git 的另一个重要的特色是:分布式。也就是说,它是用于多人(公司或团队)协同进行存档和版本控制的。
有位大神看了我们的文章后认为如果我们能讲讲分布式,那这篇文章会更加加分,那肯定没问题。

我们现代的程序员,写代码的时候上来就是用 Git,理所应当以为版本管理系统都是现在分布式的样子。殊不知,以前的版本管理系统都是集中式的。

我们先简单介绍一下什么叫集中式,还是用本文的案例:

像上图这样,有一个集中的地方管理所有文件,每个人开发只要拉取特定文件进行开发,这叫集中式开发。
集中式开发的弊端大致有以下两点:

  1. 效率。中央仓库出了问题,所有人都无法正常工作了,因为大家都依赖他拉取和推送文件。
  2. 稳定性。中央仓库挂了,存档就没了。


针对以上弊端,我们能想到的,最直接的处理方式是:每个人都保存一份仓库的拷贝。如下图所示:

有同学会问,欸,阿菌,那我还有必要学 SVN 那些集中式版本管理软件么?
当然不用,Git 的出现,已经完全颠覆了过去的集中式版本管理系统。SVN 的版本管理策略和 Git 还是有很大区别的,阿菌没有说 SVN 不好,大家要知道,这里涉及的原因很多。这是时代变化所引起的变革,以及大环境所需导致的变迁,不存在孰好孰坏的问题。
我们尝试开辟一个角度想(不一定对):在以前的年代,内存,磁盘,计算资源都是很宝贵的,当时的机器根本就不适宜支持我们在每台机器上,保存完整的工程文件存档,也不可能采用 Git 这种压缩保存整个文件原信息的策略(增量保存能省很多空间,代价是牺牲性能)。所以,使用 SVN 这样集中式的版本管理系统,或许是个很好的选择。

现在机器越来越好了,磁盘大,网络快,直接就能在每个人的机器上保存完整副本。更重要的是,Git 本身的设计非常优良,它站在 Linux 操作系统肩上发家(最初是因为想分布式开发 Linux 而创造的 Git),后来还发展出了 Github 这样的开源社区。慢慢地,大家都愿意迁移到 Git 上开发了。

再换一个角度:大家想想,如果一个工程真的非常非常庞大,单台机器不能拉取整个工程进行开发,集中式的版本控制无疑是更好的选择。
但是现在业界流行微服务,系统的拆分解耦是大势所趋,这也注定了大工程会被拆分成小工程。而体量小的工程,恰好非常适合使用分布式版本控制。
存在即合理,任何一项技术,我们在评价它时,都不能脱离时代背景和现实需求。


我们这篇文章不教操作,关于 Git 操作的文章,网上一抓一大把,各种奇技淫巧,应有尽有。

各位如果想自己玩出奇技淫巧,那就跟着阿菌一起深入数据结构探索原理吧,那些只教奇技淫巧的博客,通常都不怎么说原理,懂了原理才能更好地发掘奇技淫巧吖!

有同学可能会问:阿菌,原理懂了,但是不太能和操作对应起来,我们平时用 Git,就是一条 pull 和一条 push,两条指令走天下分支我是懂了,但这些分布式操作我还不太懂,不太能联系起来。。。

阿菌实习时的导师,曾教给阿菌一个非常重要的学习方法:当我们看到一个没接触过的东西的时候,我们首先要想 —— 如果这个东西交给你来做,你会怎么实现?


阿菌看过一点点 Git 的源码,也翻过官方文档,但是不可能在这里把这些东西全倒出来,我们尝试引导大家一点点思考。(最终的深入精确学习,还是建议大家看源码文档,想要深入学一个东西,这苦是不得不吃的)
我们沿用这个图进行讲解,在看之前,大家务必先搞清楚 object 的底层数据结构以及怎样把 object 串联起来形成分支。我们先回顾一下当时的总览图:



之前我们提到以阿叉作为主分支,是一个不太好的设计,但是不影响我们讲解,我们假设阿叉已经开发完了,远程仓库就是阿叉的仓库。

现在阿勾已经开发完了,阿勾会把他的本地仓库推送到远程仓库,阿勾的仓库是这样子的:


阿菌能猜到一些小伙伴看到这懵逼了,千万不能懵逼,一定要全文串联回忆,我们的版本管理软件,就是一条链表加树,这里的每个圈圈都是一个 commit object,他们是对应的,阿菌只是用一个小圈圈代替,以节省位置:



明白了这个之后,我们来看一下合并的流程,首先阿勾会把自己的本地仓库推送到远程仓库(主分支):



现在,大家明白,为什么合并分支会多出来一个提交了吧?



还有一些常用的指令,什么 rebase 吖,不就是调整链表么?不懂的话可以去刷刷算法题,打打基础。

不过,多人一起办公难免会遇到一些问题,比如说大家同时修改了一个文件,发生了冲突。但懂了原理后这都很好解决,大家沟通一下用谁修改的版本就好了,协商出一个不冲突的版本,然后合并就行。合并的原理上文已经提到啦,一通百通。
也正由于是多人协同办公,注定我们的软件要具备联网的能力,涉及许多网络交互,这是分布式软件必不可少滴内容。但大家要相信,最底层原理懂了,具体如何使用,如何与他人在网络中合作,那都是很简单的内容,学一个软件关键是要学透它的底层数据结构,学明白后,上层操作都会引刃而解的。
本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭