不同的版本控制系统如何处理二进制文件?

时间:2011-07-06 15:09:54

标签: svn git version-control mercurial

我听说过一些声称SVN比Git / Mercurial更好地处理二进制文件。这是真的,如果是这样,为什么呢?据我所知,没有版本控制系统(VCS)可以在相同二进制资源的两个版本之间区分和合并更改。

那么,并非所有VCS都不善于处理二进制文件吗?我不太了解特定VCS实现背后的技术细节,所以可能它们有一些优点和缺点。

5 个答案:

答案 0 :(得分:21)

主要的痛点在于任何DVCS的“分布式”方面:您正在克隆所有内容(所有文件的所有历史记录)

由于二进制文件大多数都没有以delta形式存储,并且没有像文本文件一样进行压缩,因此如果要存储快速发展的二进制文件,最终会快速使用 large 存储库移动(推/拉)变得非常麻烦。

例如,对于Git,请参阅What are the git limits?

二进制文件不适合VCS可以带来的功能(差异,分支,合并),并且可以在工件存储库中更好地管理(例如Nexus)。
对于CVCS(集中式VCS)而言,这不是必需的,其中存储库可以扮演该角色并且是二进制文件的存储(即使它不是其主要角色)

答案 1 :(得分:13)

关于git和二进制文件的一个澄清。

Git正在压缩二进制文件以及文本文件。所以git并不像有人建议的那样处理二进制文件。

Git添加的任何文件都会被压缩成松散的对象。它们是二进制还是文本无关紧要。如果您有二进制文件或文本文件并提交它,则存储库将增长。如果对文件进行微小更改并再次提交,则存储库将以大约相同的数量再次增长,具体取决于压缩率。

然后你制作一个git gc。 Git会在二进制文件或文本文件中找到相似之处并将它们压缩在一起。如果相似性很大,您将获得良好的压缩。 另一方面,如果文件之间没有相似之处,那么与单独压缩它们相比,你将没有太多的增益压缩它们。

这是一个带有位图片(二进制)的测试,我稍微改变了一下:

martin@martin-laptop:~/testing123$ git init  
Initialized empty Git repository in /home/martin/testing123/.git/  
martin@martin-laptop:~/testing123$ ls -l   
total 1252  
-rw------- 1 martin martin 1279322 Jan  8 22:42 pic.bmp  
martin@martin-laptop:~/testing123$ git add .  
martin@martin-laptop:~/testing123$ git commit -a -m first  
[master (root-commit) 53886cf] first  
 1 files changed, 0 insertions(+), 0 deletions(-)  
 create mode 100644 pic.bmp  

// here is the size:  
martin@martin-laptop:~/testing123$ du -s .git  
1244    .git  

// Changed a few pixels in the picture  

martin@martin-laptop:~/testing123$ git add .  
martin@martin-laptop:~/testing123$ git commit -a -m second  
[master da025e1] second  
 1 files changed, 0 insertions(+), 0 deletions(-)  

// here is the size:  
martin@martin-laptop:~/testing123$ du -s .git  
2364    .git  

// As you can see the repo is twice as large  
// Now we run git gc to compress  

martin@martin-laptop:~/testing123$ git gc  
Counting objects: 6, done.  
Delta compression using up to 2 threads.  
Compressing objects: 100% (4/4), done.  
Writing objects: 100% (6/6), done.  
Total 6 (delta 1), reused 0 (delta 0)  

// here is the size after compression:  
martin@martin-laptop:~/testing123$ du -s .git  
1236    .git  

// we are back to a smaller size than ever...  

答案 2 :(得分:9)

Git和Mercurial都使用aplomb处理二进制文件。它们不会腐蚀它们,你可以检查它们。问题是尺寸问题。

源通常比二进制文件占用更少的空间。您可能拥有构建100Mb二进制文件的100K源文件。因此,在我的存储库中存储单个构建可能会使其增长30倍。

情况更糟:

版本控制系统通常通过某种形式的diff格式存储文件。假设我有一个100行的文件,每行平均大约40个字符。整个文件大小为4K。如果我更改该文件中的一行,并保存该更改,我只会将大约60个字节添加到我的存储库大小。

现在,让我说我编译并添加了100Mb文件。我在源代码中进行了更改(可能在更改中大约10K),重新编译并存储新的二进制构建。好吧,二进制文件通常不会很好地区分,所以我很可能会在我的存储库中添加另外100Mb的大小。做一些构建,我的存储库大小增长到几千兆字节,但我的存储库的源部分只有几十千字节。

Git和Mercurial的问题在于您通常会将整个存储库签出到您的系统中。我现在正在下载几千兆字节的版本以及几十千字节的数据,而不是仅仅下载几秒钟内可以传输的几十千字节。

也许人们说Subversion更好,因为我可以简单地在Subversion中签出我想要的版本而不是下载整个存储库。但是,Subversion没有为您提供从存储库中删除过时二进制文件的简便方法,因此您的存储库无论如何都会增长和增长。我仍然不推荐它。哎呀,即使修订控制系统允许您删除过时二进制文件的旧版本,我也不推荐它。 (Perforce,ClearCase和CVS都这样做)。它最终成为一个很大的维护问题。

现在,这并不是说你不应该存储任何二进制文件。例如,如果我正在创建一个网页,我可能有一些我需要的GIF和jpeg。将它们存储在Subversion或Git / Mercurial中没问题。它们相对较小,可能比我的代码本身变化少很多。

您不应存储的是构建对象。这些应存储在发布存储库中,并根据需要提取。 Maven和Ant w / Ivy做得很好。而且,您也可以在C,C ++和C#项目中使用Maven存储库结构。

答案 3 :(得分:2)

在Subversion中,您可以lock二进制文件,以确保没有其他人可以编辑它们。这主要是向您保证,当您锁定它时,没有其他人会修改该二进制文件。分布式VCS没有(也不能)拥有锁 - 没有中央存储库可供注册。

答案 4 :(得分:0)

文本文件具有二进制文件缺乏的自然的面向行的结构。这就是使用常见文本工具(差异)比较它们的难度。尽管应该可行,但是将差异应用于二进制文件时,可读性的优势(我们首先使用文本作为首选格式的原因)将会丢失。

至于你的建议,所有的版本控制系统“处理二进制文件都是废话”,我不知道。原则上,没有理由为什么二进制文件应该更慢处理。我宁愿说在处理文本文件时使用VCS(跟踪,差异,概述)的优势更加明显。