Проблема с большим файлом в Git
Традиционно некоторые компании и учреждения держались подальше от Git из-за неэффективности обработки больших двоичных файлов. Разработчикам видеоигр и медиа-компаниям приходится иметь дело со сложными текстурами, полноэкранными видео и высококачественными аудиофайлами. Исследовательские институты должны отслеживать большие наборы данных, которые могут быть гигабайтами или терабайтами. Git испытывает трудности с обслуживанием этих больших файлов.
Чтобы понять проблему, нам нужно взглянуть на то, как Git отслеживает файлы. Всякий раз, когда происходит фиксация, Git создает узел объекта с указателем на его родителя или нескольких родителей. Модель данных Git известна как ориентированный ациклический граф (DAG). Модель DAG гарантирует, что отношения между родительскими и дочерними элементами никогда не образуют никаких циклов.
Мы можем проверить внутреннюю работу модели DAG. Вот пример трех коммитов в репозитории:
$ git log --oneline2beb263 Commit C: добавлено изображение1.jpeg
866178e Коммит B: добавить b.текст
d48dd8b Commit A: добавить.текст
В коммитах A и B мы добавили текстовый файл a.txt и b.текст. Затем в коммите C мы добавили файл изображения с именем image1.jpeg. Мы можем визуализировать DAG следующим образом:
Фиксация C Фиксация B Фиксация A2beb263 -> 866178e -> d48dd8b
Если мы проверим последний коммит с помощью следующей команды:
$ git cat-file -p 2beb263дерево 7cc17ba5b041fb227b9ab5534d81bd836183a4e3
родитель 866178e37df64d9f19fa77c00d5ba9d3d4fc68f5
автор Зак Х
коммиттер Зак Х
Фиксация C: добавлено изображение1.jpeg
Мы видим, что у коммита C (2beb263) есть коммит B (866178e) в качестве родительского. Теперь, если мы проверим объект дерева коммита C (7cc17ba), мы увидим капли (большие двоичные объекты):
$ git cat-file -p 7cc17ba100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 a.текст
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 b.текст
100644 blob a44a66f9e06a8faf324d3ff3e11c9fa6966bfb56 image1.jpeg
Мы можем проверить размер капли изображения:
$ git cat-file -s a44a66f9e871680
Git отслеживает изменения в этой древовидной структуре. Внесем изменения в изображение1.jpeg и проверим историю:
$ git log --oneline2e257db Фиксация D: измененное изображение1.jpeg
2beb263 Commit C: добавлено изображение1.jpeg
866178e Коммит B: добавить b.текст
d48dd8b Commit A: добавить.текст
Если мы проверим объект Commit D (2e257db):
$ git cat-file -p 2e257dbдерево 2405fad67610acf0f57b87af36f535c1f4f9ed0d
родитель 2beb263523725e1e8f9d96083140a4a5cd30b651
автор Зак Х
коммиттер Зак Х
Фиксация D: измененное изображение1.jpeg
И дерево (2405fad) внутри него:
$ git cat-file -p 2405fad100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 a.текст
100644 blob e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 b.текст
100644 blob cb4a0b67280a92412a81c60df36a15150e713095 image1.jpeg
Обратите внимание, что хеш SHA-1 для image1.jpeg изменился. Это означает, что он создал новый BLOB-объект для image1.jpeg. Мы можем проверить размер нового BLOB-объекта:
$ git cat-file -s cb4a0b61063696
Вот способ визуализировать приведенную выше структуру DAG:
Зафиксировать D Зафиксировать C Зафиксировать B Зафиксировать A| | | |
2e257db -> 2beb263 -> 866178e -> d48dd8b
| | | |
Дерево4 Дерево3 Дерево2 Дерево1
| | | |
BLOB-объекты BLOB-объекты BLOB-объекты
Каждый объект фиксации поддерживает свое собственное дерево. Внутри этого дерева хранятся капли. Git оптимизирует пространство, гарантируя, что он сохраняет только различия и использует сжатие для хранения. Но для изменения двоичных файлов Git должен хранить целые файлы в больших двоичных объектах, потому что трудно определить различия. Кроме того, изображения, видео и аудио файлы уже сжаты. В результате для каждого экземпляра измененного двоичного файла дерево заканчивается большим двоичным объектом.
Давайте представим пример, в котором мы вносим несколько изменений в файл изображения размером 100 МБ.
Зафиксировать C -> Зафиксировать B -> Зафиксировать A| | |
Дерево3 Дерево2 Дерево1
| | |
Blob3 Blob2 Blob1
300 МБ 200 МБ 100 МБ
Каждый раз, когда мы меняем файл, Git должен создать большой двоичный объект размером 100 МБ. Таким образом, только после 3 коммитов размер репозитория Git составляет 300 МБ. Как видите, размер репозитория Git может быстро увеличиться. Поскольку Git - это распределенный контроль версий, вы собираетесь загрузить весь репозиторий в свой локальный экземпляр и много работать с ветками. Таким образом, большие двоичные объекты становятся узким местом в производительности.
Git LFS решает проблему, заменяя большие двоичные объекты на файлы облегченных указателей (PF) и создавая механизм для хранения больших двоичных объектов в другом месте.
Зафиксировать C -> Зафиксировать B -> Зафиксировать A| | |
Дерево3 Дерево2 Дерево1
| | |
PF3 PF2 PF1
Локально Git хранит большие двоичные объекты в кэше Git LFS, а удаленно хранит их в хранилище Git LFS на GitHub или BitBucket.
PF1 -> Blob1PF2 -> Blob2
PF3 -> Blob3
Теперь, когда вы имеете дело с репозиторием Git, легкие файлы PF будут использоваться для рутинных операций. Капли будут извлечены только при необходимости. Например, если вы проверяете Commit C, то Git LFS найдет указатель PF3 и загрузит Blob3. Таким образом, рабочий репозиторий будет компактнее, а производительность повысится. Вам не нужно беспокоиться о файлах указателя. Git LFS будет управлять ими за кулисами.
Установка и запуск Git LFS
Ранее предпринимались попытки решить проблему с большим файлом Git. Но Git LFS преуспел, потому что он прост в использовании. Вам просто нужно установить LFS и указать, какие файлы отслеживать.
Вы можете установить Git LFS, используя следующие команды:
$ sudo apt-get install software-properties-common$ curl -s https: // packagecloud.io / установка / репозитории / github / git-lfs / скрипт.деб.ш | sudo bash
$ sudo apt-get install git-lfs
$ git lfs install
После того, как вы установили Git LFS, вы можете отслеживать нужные файлы:
$ git lfs track "*.jpeg "Отслеживание "*.jpeg "
Вывод показывает, что Git LFS отслеживает файлы JPEG. Когда вы начнете отслеживать с помощью LFS, вы найдете .gitattributes файл, в котором будет запись, показывающая отслеживаемые файлы. В .gitattributes файл использует ту же нотацию, что и .gitignore файл. Вот как содержимое .gitattributes выглядит:
$ cat .gitattributes*.jpeg filter = lfs diff = lfs merge = lfs -text
Вы также можете узнать, какие файлы отслеживаются, используя следующую команду:
$ git lfs trackСписок отслеживаемых шаблонов
*.jpeg (.gitattributes)
Если вы хотите прекратить отслеживание файла, вы можете использовать следующую команду:
$ git lfs untrack "*.jpeg "Отслеживание "*.jpeg "
Для общих операций Git вам не нужно беспокоиться о LFS. Он автоматически позаботится обо всех бэкэнд-задачах. После того, как вы настроили Git LFS, вы можете работать с репозиторием, как с любым другим проектом.
Дальнейшее изучение
Чтобы узнать о более сложных темах, просмотрите следующие ресурсы:
- Перемещение репозитория Git LFS между хостами
- Удаление локальных файлов Git LFS
- Удаление удаленных файлов Git LFS с сервера
- Веб-сайт Git LFS
- Документация Git LFS
Рекомендации:
- git-lfs.github.com: репозиторий GitHub
- github.com / git-lfs / git-lfs / tree / master / docs: документация GitHub для Git LFS
- атласский.com / git / tutorials / git-lfs: учебные пособия по Atlassian
- YouTube.com: Что такое Git LFS
- YouTube.com: Отслеживание огромных файлов с помощью Git LFS, автор Тим Петтерсен, Atlassian
- YouTube.com: Управление огромными файлами в нужном хранилище с помощью Git LFS, YouTube
- YouTube.com: Git Large File Storage - Как работать с большими файлами, YouTube
- Аскубунту.com / questions / 799341: как установить-git-lfs-on-ubuntu-16-04
- github.com / git-lfs / git-lfs / blob / master / УСТАНОВКА.md: Руководство по установке