我刚刚在http://blip.tv/play/Aeu2CAI上看到了第一个Git教程.
Git如何存储所有文件的所有版本,以及它如何在空间上比Subversion更经济,而Subversion只保存最新版本的代码?
我知道这可以使用压缩来完成,但这会以速度为代价,但这也说Git要快得多(尽管它获得最大值的是它的大部分操作都处于脱机状态).
所以,我猜是这样的
Git广泛压缩数据
它仍然更快,因为uncompression + work
仍然比network_fetch + work
我对么?甚至接近?
我假设您在询问git克隆(完整存储库+结帐)是否可能小于Subversion中的签出源.或者你的意思是其他什么?
评论中回答了这个问题
首先,您应该考虑到结帐(工作版本)Subversion将pristine副本(最新版本)存储在这些.svn
子目录中.原始副本在Subversion中未压缩存储.
其次,git使用以下技术使存储库更小:
每个版本的文件只存储一次; 这意味着如果你在10个版本(10个提交)中只有一个文件的两个不同版本,git只存储那两个版本,而不是10个版本.
对象(和增量,见下文)是压缩存储的; 编程中使用的文本文件压缩得非常好(约为原始大小的60%,或者压缩大小减少40%)
重新包装后,对象以分层的形式存储,与其他版本不同; 另外,git尝试以这样一种方式对delta链进行排序,即delta主要由删除组成(在通常情况下,增长文件是新近顺序); IIRC三角洲也被压缩.
首先,涉及网络的任何操作都比本地操作慢得多.因此,例如将工作区域的当前状态与某些其他版本进行比较,或获取日志(历史记录),在Subversion中涉及网络连接和网络传输,并且在Git中是本地操作,当然在Subversion中要比在Git.BTW.这是集中式版本控制系统(使用客户端 - 服务器工作流程)和分布式版本控制系统(使用对等工作流程)之间的区别,不仅仅是Subversion和Git之间.
其次,如果我理解正确,那么现在的限制不是CPU而是IO(磁盘访问).因此,由于压缩(并且能够在存储器中对其进行mmap)而必须从磁盘读取较少数据的增益可能克服了必须解压缩数据的损失.
第三,Git的设计考虑了性能(参见例如Git Wiki上的GitHistory页面):
索引存储文件的统计信息,Git使用它来判断文件是否被修改而不检查文件(参见例如core.trustctime
config变量).
最大增量深度限制为pack.depth
,默认为50. Git具有增量缓存以加快访问速度.有(生成的)packfile索引可以快速访问packfile中的对象.
Git小心不要触摸它不需要的文件.例如,当切换分支或倒带到另一个版本时,Git仅更新已更改的文件.这种理念的结果是Git只支持非常小的关键字扩展(至少开箱即用).
Git使用自己版本的LibXDiff库,现在也用于diff和merge,而不是调用外部差异/外部合并工具.
Git尝试最小化延迟,这意味着良好的感知性能.例如,它git log
尽可能快地输出" "的第一页,即使生成完整的历史记录需要更多时间,您几乎可以立即看到它.它不会等待在显示之前生成完整的历史记录.
在获取新更改时,Git会检查与服务器共有的对象,并仅以瘦包文件的形式发送(压缩)差异.不可否认,Subversion可以(或者可能默认情况下)在更新时也只发送差异.
我不是Git黑客,我可能错过了Git用于提高性能的一些技巧和窍门.但请注意,Git大量使用POSIX(如内存映射文件),因此MS Windows上的增益可能不是很大.
不是一个完整的答案,但那些评论(来自AlBlue)可能有助于问题的空间管理方面:
这里有一些值得澄清的事情.
首先,可以拥有比SVN存储库更大的Git存储库 ; 我希望我并不暗示那种情况从未发生过.但是,实际上,通常情况下,Git存储库占用的磁盘空间少于等效的SVN存储库.
你引用的一件事是Apache的单个SVN存储库,这显然是庞大的.但是,只需看一下git.apache.org
,您就会注意到每个Apache项目都有自己的Git存储库.真正需要的是对类似的比较; 换句话说,检查(abdera)SVN项目与(abdera)Git存储库的克隆.我能够结账
git://git.apache.org/abdera.git
.在磁盘上,它消耗了28.8Mb.
然后我检查了SVN版本http://svn.apache.org/repos/asf/abdera/java/trunk/
,它消耗了34.3Mb.
这两个数字都来自RAM空间中单独安装的分区,引用的数字是从磁盘中获取的字节数.
如果使用du -sh
作为测试手段,Git结账为11Mb,SVN结账为17Mb.Apache Abdera的Git版本允许我使用任何版本的历史记录,包括当前版本; SVN只能备份当前签出的版本.但它在磁盘上占用的空间更少.
怎么样,你可能会问?
好吧,首先,SVN创建了更多文件.SVN结账有2959个文件; 相应的Git存储库有845个文件.
其次,虽然SVN
.svn
在层次结构的每个级别都有一个文件夹,但Git repo.git
在顶层只有一个存储库.这意味着(除其他事项外)从一个目录重命名到另一个目录在Git中的影响比在SVN中的影响相对较小,无论如何,SVN已经具有相对较小的影响.第三,Git将其数据存储为压缩对象,而SVN将它们存储为未压缩的副本.进入任何
.svn/text-base
目录,您将找到(基本)文件的未压缩副本.
Git有一种机制可以将所有文件(实际上是所有历史记录)压缩成包文件.在Abdera的情况下,.git/objects/pack/
在4.8Mb文件中有一个.pack文件(包含所有历史记录).
因此,在这种情况下,存储库的大小(大致)与当前检出的代码大小相同,但我不希望总是如此.无论如何,你是对的,历史可以增长到超过当前结账的总大小; 但由于SVN的工作方式,它实际上必须接近两倍大小才能产生很大的不同.即使这样,磁盘空间减少也不是使用DVCS的主要原因; 对某些事情来说,这是一个优势,当然,但这并不是人们使用它的真正原因.
请注意,Git(和Hg,以及其他DVCS)确实遇到了一个问题,即检查(大)二进制文件然后删除它们,因为它们仍会显示在存储库中并占用空间,即使它们不是最新的.文本压缩为文本文件处理这些事情,但二进制文件更是一个问题.(有一些管理命令可以更新Git存储库的内容,但它们的开销/管理成本略高于CVS; git filter-branch就像
svnadmin dump/filter/load
.)
至于速度方面,我在我的" 用远程操作进行颠覆的速度有多快? "中提到了这一点(就像Linus在谷歌的演示文稿中所说的那样 :(在这里解释)"任何涉及网络的东西都会扼杀表演")
而GitBenchmark文件由提到的JakubNarębski是一个很好的补充,即使它不与Subversion直接处理.
它确实列出了在DVCS性能方面需要监视的操作类型.
在这个SO问题中提到了其他Git基准.