2011-07-06 114 views
29

我听说过一些SVN处理二进制文件比Git/Mercurial更好的说法。这是真的吗?如果是这样的话,为什么?就我所能想象的,没有版本控制系统(VCS)可以区分和合并相同二进制资源的两个修订版本之间的更改。不同的版本控制系统如何处理二进制文件?

那么,是不是所有的VCS在处理二进制文件方面都不好?我不是很了解特定VCS实现背后的技术细节,所以他们可能有一些优点和缺点。

+20

我认为,这*不*停课“没有建设性”为一对夫妇建议。这里有*关于存储二进制文件的不同方式的真实事实,以及DVCS中的签出存储所有内容的方式等等。对于什么更好会有一些争论,但我认为这样的问题是有价值的。 –

+0

有[很多](http://stackoverflow.com/questions/3601672/git-and-binary-file)[of](http://stackoverflow.com/questions/2983635/can-git-mercurial- svn-or-other-version-control-tools-work-well-when-project-tr)[非常接近](http://stackoverflow.com/questions/1126239/git-or-subversion-for-binary-files )[questions](http://stackoverflow.com/questions/3037664/does-any-version-control-system-like-svn-git-or-mercurial-let-you-keep-latest)[around](http ://stackoverflow.com/questions/5234318/version-control-for-large-binary-files-and-1tb-repositories)... – huitseeker

+0

...和我[意思](http://stackoverflow.com/questions/275147/svn-optimizations-to-keep-large-repositories-responsive)[a whole](http:// stackoverflow。com/questions/540535/managing-large-binary-files-with-git)[lot](http://stackoverflow.com/questions/5025998/versioning-when-binary-and-text-files-are-involved) 。 – huitseeker

回答

21

主要痛点在任何DVCS的“分布式”的方面:你是克隆一切(所有文件的全部历史)

由于二进制文件并不存储在增量的大部分,如果您正在存储快速演变的二进制文件,则最终会很快得到一个大版本库,这对于移动(推/拉)变得非常麻烦。

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

二进制文件不适合VCS可以带来的功能(diff,branch,merge),并且在工件存储库(例如Nexus)中可以更好地进行管理。
这是没有必要的CVCS(集中式VCS)中,仓库可以扮演这一角色,并存储为二进制文件(即使它不是它的主要作用)

+2

非常好。但是,我不喜欢在任何VCS中放入二进制文件。这并不是说Git和SVN不能很好地处理二进制文件,但正如你所说:它们会占用很多空间。在Git中,尤其是在您下载_checkout_上的整个存储库之后。此外,这不是一个全部或没有规则。二进制文件如GIF和JPEG可能应该存储在版本控制系统中。你不想存储的是构建结果。 –

+0

你不*有*克隆一切。我知道Mercurial允许你指定你想克隆历史的多少(在TortoiseHG中“克隆到修订”)。这是保持本地存储库大小不变的好方法。这个功能通常足以提供一个包含适度二进制文件更新的回购协议的一致体验。 – nbevans

+2

@NathanE我认为你误解了Clone to Revision--它是从0到你指定的版本。所以确实,你可以只抓取最古老的几个版本,但如果你想要什么是当前你需要抓住一切。 –

0

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

至于你的建议,所有的版本控制系统“在处理二进制文件是废话”,我不知道。原则上,二进制文件处理速度较慢是没有道理的。我宁愿说在处理文本文件时使用VCS的优点(跟踪,差异,总览)更为明显。

9

的Git和Mercurial都处理与沉着的二进制文件的情况下。他们不会腐败他们,你可以检查他们进出。问题是规模之一。

源通常占用的空间比二进制文件要少。您可能有100K的源文件构建100Mb二进制文件。因此,在我的存储库中存储单个构建可能会导致它增长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存储库结构。

+1

而不是添加另一个答案,说完全一样的有关Mercurial,我编辑你的答案。希望没关系。 –

2

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

+0

这个重要性不能被夸大。在大多数工作流程中,当某人正在处理二进制文件时,他们将其锁定。这会积极阻止其他人这样做。如果没有这种预防,会发生什么事是一个人会检查它,另一个人将不得不重做他们的工作。这是不可接受的。 –

+0

虽然锁定在某种程度上是有用的,但它并不妨碍人们打开本地二进制文件并修改它们。 – Tower

+0

@rfactor如果你设置了'svn:needs-lock'属性,那么Subversion使文件为只读直到你获得锁定。 – robert

10

一个关于git和二进制文件的说明。

Git压缩二进制文件以及文本文件。所以git在处理二进制文件时并不是垃圾,正如某人所建议的那样。

Git添加的任何文件都将被压缩为松散对象。它们是二进制文本还是文本无关紧要。如果你有一个二进制或文本文件,并提交它,存储库将增长。如果您对该文件进行了较小的更改并再次提交,则根据压缩比率,您的存储库将以大约相同的量再次增长。

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

这里是一个位图图片(二进制),我改变一点点的测试:

[email protected]:~/testing123$ git init 
Initialized empty Git repository in /home/martin/testing123/.git/ 
[email protected]laptop:~/testing123$ ls -l 
total 1252 
-rw------- 1 martin martin 1279322 Jan 8 22:42 pic.bmp 
[email protected]:~/testing123$ git add . 
[email protected]:~/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: 
[email protected]:~/testing123$ du -s .git 
1244 .git 

// Changed a few pixels in the picture 

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

// here is the size: 
[email protected]:~/testing123$ du -s .git 
2364 .git 

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

[email protected]:~/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: 
[email protected]:~/testing123$ du -s .git 
1236 .git 

// we are back to a smaller size than ever... 
相关问题