Как различные системы управления версиями обрабатывают двоичные файлы?

Я слышал некоторые утверждения о том, что SVN обрабатывает двоичные файлы лучше, чем Git/Mercurial. Это правда, и если да, то почему? Насколько я могу себе представить, никакая система контроля версий (VCS) не может различать и объединять изменения между двумя версиями одних и тех же двоичных ресурсов.

Итак, не все ли VCS плохо при обработке двоичных файлов? Я не очень разбираюсь в технических деталях, стоящих за конкретными реализациями VCS, поэтому, возможно, у них есть некоторые плюсы и минусы.

Ответ 1

Основная точка боли в "распределенном" аспекте любого DVCS: вы клонируете все (всю историю всех файлов)

Поскольку двоичные файлы не хранятся в delta для большинства из них и не сжимаются, а также текстовый файл, если вы храните быстро развивающиеся двоичные файлы, вы быстро получаете большой репозиторий, который становится намного громоздким для перемещения (тяни-Толкай).

Например, для Git см. Каковы ограничения Git?.

Бинарники не подходят для функции, которую VCS может принести (diff, branch, merge) и лучше управляться в репозитории артефактов (например, Nexus, например).
Это не обязательно для CVCS (централизованного VCS), где репозиторий может играть эту роль и быть хранилищем для двоичных файлов (даже если это не его основная роль)

Ответ 2

Одно пояснение о git и двоичных файлах.

Git сжимает двоичные файлы, а также текстовые файлы. Таким образом, git не дерьмо при обработке двоичных файлов, как кто-то предложил.

Любой файл, добавляемый git, будет сжат в свободные объекты. Неважно, являются ли они двоичными или текстовыми. Если у вас есть двоичный или текстовый файл, и вы его фиксируете, репозиторий будет расти. Если вы внесете небольшое изменение в файл и снова зафиксируете, ваш репозиторий будет расти снова примерно на том же уровне, в зависимости от степени сжатия.

Затем вы создаете git gc. git найдет сходство в двоичных или текстовых файлах и сжимает их вместе. У вас будет хорошее сжатие, если сходство велико. Если, с другой стороны, нет никакого сходства между файлами, вы не будете иметь большого выигрыша, сжимающего их вместе по сравнению с их сжатием по отдельности.

Вот тест с битовым отображением (двоичным), который я немного изменил:

[email protected]:~/testing123$ git init  
Initialized empty Git repository in /home/martin/testing123/.git/  
[email protected]:~/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...  

Ответ 3

Git и Mercurial обрабатывают двоичные файлы с апломбом. Они не повреждают их, и вы можете проверить их. Проблема заключается в размере.

Источник обычно занимает меньше места, чем двоичные файлы. У вас может быть 100K исходных файлов, которые строят двоичный файл 100Mb. Таким образом, сохранение одной сборки в моем репозитории может привести к ее росту в 30 раз больше.

И это еще хуже:

Системы управления версиями обычно хранят файлы через формат формы. Скажем, у меня есть файл из 100 строк, и каждая строка содержит около 40 символов. Весь файл размером 4K. Если я изменяю строку в этом файле и сохраняю это изменение, я добавляю только около 60 байт к размеру моего репозитория.

Теперь, скажем, я скомпилировал и добавил, что 100Mb файл. Я вношу изменения в свой исходный код (возможно, 10K или около того), перекомпилировать и сохранить новую двоичную сборку. Ну, двоичные файлы обычно не отличаются очень хорошо, поэтому, скорее всего, я добавлю еще 100 Мб размера в мой репозиторий. Сделайте несколько сборок, а размер моего репозитория увеличивается до нескольких гигабайт, но исходная часть моего репозитория составляет всего несколько десятков килобайт.

Проблема с Git и Mercurial заключается в том, что вы обычно проверяете весь репозиторий на свою систему. Вместо того, чтобы просто загружать несколько десятков килобайт, которые можно перенести за несколько секунд, теперь я загружаю несколько гигабайт сборок вместе с несколькими десятками килобайт данных.

Возможно, люди говорят, что Subversion лучше, так как я могу просто проверить версию, которую я хочу в Subversion, и не загружать весь репозиторий. Однако Subversion не дает вам простой способ удалить устаревшие двоичные файлы из вашего репозитория, поэтому ваш репозиторий будет расти и расти в любом случае. Я все еще не рекомендую. Черт, я даже не рекомендую его, даже если система контроля версий позволяет удалить старые версии устаревших двоичных файлов. (Perforce, ClearCase и CVS все делают). Это просто заканчивается большой головной болью обслуживания.

Теперь это не означает, что вы не должны хранить двоичные файлы. Например, если я создаю веб-страницу, у меня, вероятно, есть некоторые gif и jpeg, которые мне нужны. Нет проблем с хранением данных в Subversion или Git/Mercurial. Они относительно малы и, вероятно, меняются намного меньше, чем сам мой код.

То, что вы не должны хранить, - это построенные объекты. Они должны храниться в репозитории выпуска и извлекаться по мере необходимости. Maven и Ant w/Ivy отлично справляются с этим. Кроме того, вы можете использовать структуру репозитория Maven в проектах C, С++ и С#.

Ответ 4

В Subversion вы можете lock бинарные файлы, чтобы никто не мог их редактировать. Это в основном гарантирует, что никто другой не изменит этот двоичный файл, пока вы его заблокировали. Распределенные VCS не имеют (и не могут) блокировок - нет центрального хранилища для их регистрации.

Ответ 5

Текстовые файлы имеют естественную линейную привязку, которой не хватает двоичных файлов. Вот почему их сложнее сравнивать с помощью обычных текстовых инструментов (diff). В то время как это должно быть возможно, преимущество чтения (причина, по которой мы используем текст в качестве нашего предпочтительного формата в первую очередь) будет потеряна при применении diff к двоичным файлам.

Что касается вашего предположения, что все системы управления версиями "дерьмо при обработке двоичных файлов", я не знаю. В принципе, нет причин, по которым двоичный файл должен обрабатываться медленнее. Я бы сказал, что преимущества использования VCS (отслеживание, различие, обзор) более очевидны при обработке текстовых файлов.