每个人似乎都同意的一件事是,Git对于大二进制点来说并不是很好。请记住,二进制blob与大型文本文件不同;您可以在大型文本文件上使用Git而不存在任何问题,但是Git不能对不透水的二进制文件执行太多操作,只需将其视为一个大的实心黑匣子,并将其按原样提交。
根据https://opensource.com/life/16/8/how-manage-binary-blobs-git-part-7
每个人似乎都同意的一件事是,Git对于大二进制点来说并不是很好。请记住,二进制blob与大型文本文件不同;您可以在大型文本文件上使用Git而不存在任何问题,但是Git不能对不透水的二进制文件执行太多操作,只需将其视为一个大的实心黑匣子,并将其按原样提交。 假设您有一个复杂的3D模型,用于您正在制作的令人兴奋的第一人称益智游戏,并将其保存为二进制格式,从而生成一个1G文件。您只需提交一次,在存储库的历史记录中添加一个千兆字节。稍后,您给模型一个不同的发型并提交您的更新;Git不能区分头发与头部或模型的其余部分,所以您刚刚提交了另一个千兆字节。然后你改变模型的眼睛颜色,并提交一个小的变化:另一个千兆字节。这是三千兆字节的一种模式,几个小的变化,一时兴起。一个游戏中所有的资产都要按比例计算,你就有了一个严重的问题。
我的理解是,文本文件和二进制文件没有区别,Git将每个提交的所有文件全部存储(创建一个校验的blob),不变的文件只是指向一个已经存在的blob。如何存储和压缩所有这些小块是另一个问题,我不知道其中的细节,但我会假设,如果引用中的各种1GB文件或多或少是相同的,那么一个好的压缩算法就会解决这个问题,如果它们是重复的,那么它们甚至可以存储在小于1GB的总数中。这种推理应该适用于二进制文件和文本文件。
与此相反,这句话继续说
与像.obj格式这样的文本文件形成对比。一个提交存储所有东西,就像另一个模型一样,但是.obj文件是一系列描述模型顶点的纯文本行。如果修改模型并将其保存回.obj,Git可以逐行读取两个文件,创建更改的差异,并处理相当小的提交。模型变得越精细,提交的获取就越小,这是一个标准的Git用例。它是一个大文件,但是它使用一种覆盖或稀疏存储方法来构建数据当前状态的完整图片。
我的理解正确吗?这句话不正确吗?
发布于 2018-12-06 09:17:21
Git确实会存储完整的文件,所以如果你有2个二进制文件,只要做一个小小的改动,它就会占用两倍的空间。观察。
% git init
Initialized empty Git repository in /tmp/x/.git/
{master #}% [/tmp/x]
{master #}% du -sh .git
100K .git
{master #}% dd if=/dev/urandom of=./test count=1 bs=10M
1+0 records in
1+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.102277 s, 103 MB/s
{master #%}% ls -sh test
10M test
{master #%}% git add test
git co%
{master #}% git commit -m "Adds test"
[master (root-commit) 0c12c32] Adds test
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test
{master}% du -sh .git
11M .git
我创建了一个10 it的文件并添加并提交了它。存储库现在的大小为10 in。
如果我做了个小小的改变,然后再做一次,
{master}% e test # This is an invocation of my editor to change a few bytes.
nil
{master}% git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: test
no changes added to commit (use "git add" and/or "git commit -a")
{master *}% git add test
{master +}% git commit -m "Updates test a little"
[master 99ed99a] Updates test a little
1 file changed, 0 insertions(+), 0 deletions(-)
{master}% du -sh .git
21M .git
需要20 It。两次10 Two文件。
但是,这是存储库的"松散对象“格式,其中每个blob是磁盘上的一个单独文件。
您可以将所有这些打包到一个git包文件中(这是在您推送等过程中完成的)。看看会发生什么。
{master}% git gc
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), done.
Total 6 (delta 1), reused 0 (delta 0)
{master}% du -sh .git
11M .git
现在,它只在包装文件中存储一次blob和差异。这与每一次提交都是不同的,只存储差异。就是将对象本身打包到一个文件中。
发布于 2018-12-06 16:10:56
在文本中您是正确的,二进制文件实际上只是blob对象。如果这是故事的全部内容,事情就会简单一些,但事实并非如此,所以事实并非如此。
(还可以指示Git对输入文件执行各种筛选操作。在这里,文本文件和二进制文件在过滤器的作用上没有区别,但是在默认情况下应用过滤器是有区别的:如果使用自动模式,Git将过滤Git认为是文本的文件,而不是-过滤Git认为是二进制的文件。但是,只有在使用自动检测和CRLF /LF仅限行结束转换时,这才是重要的。
如果引用中的各种1GB文件或多或少是相同的,那么一个好的压缩算法就可以计算出这一点,如果它们是重复的,那么它们甚至可以存储在小于1GB的总和中。
也许,也许不是。Git有两种独立的压缩算法。作为努法尔易卜拉欣赛义德,这两个三角压缩-is中的一个只应用于Git所称的pack文件。另一个是zlib,它适用于所有东西。
Zlib是一种通用的压缩算法,依赖于特定的建模过程(背景见是否有“完美”压缩的算法? )。它在纯文本上表现得很好,而在一些二进制文件上则不太好。它倾向于使已经压缩的文件更大,所以如果您的1GB输入已经被压缩,那么在zlib压缩之后,它们可能会(稍微)大一些。但所有这些都是一般性的;要了解它如何处理特定的数据,诀窍是在特定的数据上运行它。
Git使用的增量编码发生在zlib压缩之前,并且确实可以处理二进制数据。本质上,它发现在“更早”和“稍后”对象中匹配的长二进制字节序列(此处对“更早”和“稍后”的定义相当松散,但由于讨论的原因,Git对对象强制执行特定的遍历和比较顺序),如果可能的话,将N字节的长序列替换为“引用更早的对象,从偏移量O中获取N个字节”。
如果您在大型二进制文件上尝试这一点,那么它通常对具有某种数据局部性的关联的、大型的、未压缩的二进制文件非常有效,因为“稍后”二进制文件往往有大量“早期”文件的长重复,对于大型压缩二进制文件非常糟糕,或者表示数据结构的二进制文件被洗牌太多(因此重复的二进制字符串变得非常零散,也就是说,不再长了)。因此,它又一次依赖于数据:尝试进入您的特定数据,看看它是否适合您。
https://stackoverflow.com/questions/53647783
复制相似问题