Есть ли разница между тем, как Git хранит текстовые и бинарные файлы? - PullRequest
0 голосов
/ 06 декабря 2018

Единственное, с чем все соглашаются, это то, что Git не подходит для больших двоичных двоичных объектов.Имейте в виду, что двоичный двоичный объект отличается от большого текстового файла;вы можете без проблем использовать Git для больших текстовых файлов, но Git не может сделать ничего с непроницаемым двоичным файлом, за исключением того, что обрабатывает его как один большой сплошной черный ящик и фиксирует его как есть.

Согласно https://opensource.com/life/16/8/how-manage-binary-blobs-git-part-7:

Одна вещь, с которой все согласны, это то, что Git не подходит для больших двоичных двоичных объектов.Имейте в виду, что двоичный двоичный объект отличается от большого текстового файла;вы можете без проблем использовать Git для больших текстовых файлов, но Git не может сделать ничего с непроницаемым двоичным файлом, за исключением того, что он рассматривается как один большой сплошной черный ящик и фиксирует его как есть.

Скажем, у вас естьсложную 3D-модель для новой захватывающей головоломки от первого лица, которую вы создаете, и вы сохраняете ее в двоичном формате, в результате получается файл объемом 1 гигабайт.Вы делаете это один раз, добавляя гигабайт в историю вашего хранилища.Позже вы даете модели другую прическу и фиксируете свое обновление;Git не может отличить волосы от головы или остальной части модели, поэтому вы только что отправили еще один гигабайт.Затем вы меняете цвет глаз модели и фиксируете это небольшое изменение: еще один гигабайт.Это три гигабайта для одной модели с небольшими изменениями, внесенными по прихоти.Масштабируйте все ресурсы игры, и у вас возникнет серьезная проблема.

Насколько я понимаю, нет разницы между текстовыми и двоичными файлами, и Git сохраняет все файлы каждого коммита в своихцелостность (создание контрольной суммы большого двоичного объекта), при этом неизмененные файлы просто указывают на уже существующий большой двоичный объект.Как все эти BLOB-объекты хранятся и сжимаются - это другой вопрос, детали которого я не знаю, но я бы предположил, что если различные файлы объемом 1 ГБ в кавычках более или менее одинаковы, хороший алгоритм сжатия определит это.и может быть в состоянии сохранить их все в объеме менее 1 ГБ, если они повторяются.Это рассуждение должно относиться как к двоичным, так и к текстовым файлам.

Вопреки этому, цитата продолжает говорить

Сравните это с текстовым файлом, подобным формату .obj.Один коммит хранит все, как и в другой модели, но файл .obj представляет собой серию строк простого текста, описывающих вершины модели.Если вы измените модель и сохраните ее обратно в .obj, Git может читать два файла построчно, создавать различия изменений и обрабатывать довольно небольшой коммит.Чем более изящной становится модель, тем меньше становятся коммиты, и это стандартный вариант использования Git.Это большой файл, но он использует своего рода метод наложения или разрежения для создания полной картины текущего состояния ваших данных.

Верно ли мое понимание?Неверная цитата?

Ответы [ 2 ]

0 голосов
/ 06 декабря 2018

Вы правы в том, что текстовые и двоичные файлы на самом деле являются просто объектами BLOB.Если бы это было все, что было в истории, все было бы проще, но это не так, поэтому они не.: -)

(Вы также можете указать Git выполнить различные операции фильтрации входных файлов. Здесь опять нет разницы между текстовыми и двоичными файлами с точки зрения того, что фильтры делают , но - это разница в , когда фильтры применяются по умолчанию: Если вы используете автоматический режим, Git отфильтрует файл, который Git считает текстом,и не фильтровать файл, который Git считает двоичным. Но это имеет значение только в том случае, если вы используете автоматическое обнаружение и преобразование конца строки только для CRLF / LF.)

Я бы предположил, что если бы различныеФайлы 1ГБ в цитате более или менее одинаковы, хороший алгоритм сжатия это выяснит и может сохранить все из них даже в объеме менее 1ГБ, если они повторяются ...

Может быть, а может и нет.Git имеет два отдельных алгоритма сжатия.Как сказал Нуфал Ибрагим , один из этих двух - дельта-сжатие - применяется только в том, что Git называет пакетными файлами .Другой - zlib , который применяется ко всему.

Zlib - это общий алгоритм сжатия, основанный на конкретном процессе моделирования (см. Есть ли алгоритм для "идеального")?сжатие? для фона).Он имеет тенденцию работать довольно хорошо на обычном тексте, и не очень хорошо на некоторых двоичных файлах.Он имеет тенденцию делать уже сжатые файлы больше , поэтому, если ваши входные данные в 1 ГБ уже сжаты, они, вероятно, будут (незначительно) больше после сжатия zlib.Но все это общности;чтобы выяснить, как он работает с вашими конкретными данными, нужно запустить его на ваших конкретных данных.

Дельта-кодирование, которое использует Git, происходит «до» сжатия zlib и работает с двоичными данными.По сути, он находит длинные двоичные последовательности байтов, которые совпадают в объектах «ранее» и «позже» (здесь «ранее» и «позже» определены довольно свободно, но Git навязывает определенный порядок обхода и сравнения объектов по причинам)обсуждается здесь ) и, если возможно, заменяет некоторую длинную последовательность из N байтов на «ссылаясь на более ранний объект, захватывает N байтов из смещения O».

Если вы попробуете это на больших двоичных файлах,оказывается, что он обычно работает довольно хорошо на парах связанных, больших, несжатых двоичных файлов, которые имеют некоторую локальность данных, так как «более поздний» двоичный файл имеет тенденцию иметь много длинных повторов«более ранний» файл и очень плохо на больших сжатых двоичных файлах или двоичных файлах, представляющих структуры данных, которые слишком часто перетасовываются (так что повторяющиеся двоичные строки стали очень фрагментированнымит. е. больше не будет ).Итак, еще раз, это в значительной степени зависит от данных: попробуйте на ваши конкретные данные , чтобы посмотреть, хорошо ли это работает для вас.

0 голосов
/ 06 декабря 2018

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 МБ, добавил и зафиксировал его.Размер хранилища составляет 10 МБ.

Если я сделаю небольшое изменение и сделаю это снова,

{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 МБ.В два раза больше 10 МБ файла.

Это, однако, формат хранилища " свободный объект ", где каждый большой двоичный объект представляет собой отдельный файл на диске.

Вы можете упаковатьвсе это в git packfile (что делается, когда вы нажимаете и т. д.) и посмотрите, что произойдет.

{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 и diff только один раз в packfile .Это отличается от каждого коммита, хранящего только diff.Дело в том, что сами объекты упакованы в один файл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...