python 保存网页快照_git 每一次暂存都会保存一次快照吗?

更正:

感谢 @孙山 的指正。我忽略了提问中是说的暂存。那下面第一段有问题,暂存区index里记录的东西的确会被替换掉。但是在添加到暂存区中时生成的对象会保留下来。如果这些对象最后被ref直接或者间接引用到了,那就会一直存在。如果最后因为某些原因变成了dangling object,那就会被gc清理掉。因为我把题目看成了commit操作而不是暂存操作,所以后面的回答是针对commit来的,但里面关于object的原理部分是一样的,只是暂存时只生成blob,而tree和commit对象要在生成新的commit操作时才生成。

(这一段有问题,但原文就保留了)首先说替换。旧版本被替换掉的话,那旧版本就丢失了,那版本控制也就不存在了。所以不是替换,而是每个版本都会存下来。以下内容在pro git的git internals那一章有具体解释,可以研究下那章内容。这里我讲下我的认识。

假如仓库只在根目录下有三个文件A、B、C,第一次commit(假设名为aaa)的时候,会把每个文件的内容保存一次,A1、B1、C1。假如三个文件内容一样,那就只会存一份内容。不管存三个也好存一个也好,这个存储对象(blob)只保存内容,不保存文件名。blob对象本身的名字是其内容的hash值(实际计算时还加了点东西)。

为了记录三个文件的文件名,其实是记录了三个文件所在的文件夹,文件夹的存储对象叫tree。tree里有什么?子文件夹或者文件。文件就是blob名加文件名,另外还有文件的属性(是否可执行等)。子文件夹就是另外一个tree对象。有一类特殊的子文件夹是子模块(submodule),对应一个commit对象。tree对象和blob对象一样,不记录自己的目录名,而是交由上层tree对象记录。tree对象本身的名字,也是自身内容的hash值。根tree就记录了一份快照。

根tree记录在commit对象里。根tree只记录了文件目录结构和内容,其他相关的信息也记录在了commit对象里。commit对象还包含了作者、提交人、基础版本(parent)的commit、commit message log。向上,commit和parent commit组成了commit链,代表了每个版本的快照;向下,commit用根tree记录了该快照的内容。而第一个commit是没有parent的,称为root commit。

现在在aaa的基础上修改了C文件,生成C2版本,然后commit生成了bbb。bbb的parent就是aaa,bbb有自己的根tree。根tree包含三个blob,前两个对应A1、B1(这两个文件没变化),第三个是C2。因为A1、B1对应的blob已经有了,所以只需要生成一个C2就可以了。如果我们回到aaa的基础上做了别的修改commit成ccc,那ccc和bbb就分叉了(diverged),代表了两个发展方向。aaa是bbb和ccc的merge base。

因为hash算法的特性,如果两个对象的名字一样,也就是hash值一样,那就说明它们对应的实际内容是一样的。这里不考虑碰撞,几率太小了。因而一样的内容在仓库里存储一份对象就可以了。

但是你可能会想到,那如果三个文件都改了,不还是要生成三个新的blob对象吗?那还是相当于存了两份代码。理论上是这样的,但这种看起来是最坏情况了。我们每次更新代码存储快照时不可能每个文件都会改到,所以实际上生成的blob对象要比每个版本的文件数乘以版本数来得少很多。

此外,git在传输数据前,会把这些对象进一步压缩。想象下两个blob文件如果内容差不多,那完全可以压缩成一个,公共部分存一份,差异部分都存。这样生成的压缩文件要比两个文件小很多。压缩过程也可以用命令主动触发。没有压缩的对象叫loose object,存在.git/objects里。压缩会把部分或所有对象压缩到一个或者多个.pack文件,另外会生成.idx文件帮助定位数据。.pack文件的大小是可以指定的。所以实际使用时,对于文本文件,压缩率会非常高,n个版本的版本数据要比n个版本的代码占的空间少很多很多。

你可能也听说过git用来存储二进制文件的效果不好。从上面说的你也可以猜出原因了,二进制blob的压缩率很低很低。为了应付二进制文件,现在可以借助git lfs来处理。

实际使用时会出现两种极端情况。第一种是二进制文件多的仓库数据特别大;第二种是仓库数据很小,但对应的实际文件非常多、占空间也很多。第二种情况的最极端情况叫git bomb,一个很小的git仓库在checkout版本时会把内存吃光。在github上有这样的仓库,搜git bomb。如果要克隆的话记得加-n参数,然后通过git log、git cat-file、git ls-tree等命令来查看。千万不要checkout。

所以除了纯二进制文件的仓库,仓库版本数据并不会很大。一般情况下,和所有版本对应的文件大小相比要小很多。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值