Управление большими двоичными файлами с помощью Git - PullRequest
513 голосов
/ 12 февраля 2009

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

  1. Скопируйте двоичные файлы вручную.
    • Pro: не уверен.
    • Против: Я категорически против этого, так как это увеличивает вероятность ошибок при настройке нового сайта / переносе старого. Создает еще одно препятствие.
  2. Управляй ими всеми с помощью Git .
    • Pro: устраняет возможность «забыть» скопировать важный файл
    • Contra: расширяет хранилище и снижает гибкость управления базой кода, а извлечение, клонирование и т. Д. Займет довольно много времени.
  3. Отдельные репозитории.
    • Pro: извлечение / клонирование исходного кода выполняется быстро, как всегда, и изображения должным образом архивируются в своем собственном хранилище.
    • Contra: Удаляет простоту наличия единственного и единственного Git-репозитория в проекте. Это, безусловно, вводит некоторые другие вещи, о которых я не думал.

Что вы думаете об этом?

Также: Кто-нибудь имеет опыт работы с несколькими репозиториями Git и управления ими в одном проекте?

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

Ответы [ 12 ]

309 голосов
/ 09 июля 2011

Я недавно обнаружил git-annex , что я считаю потрясающим. Он был разработан для эффективного управления большими файлами. Я использую его для своих фото / музыкальных (и т. Д.) Коллекций. Разработка git-приложения очень активна. Содержимое файлов может быть удалено из репозитория Git, Git отслеживает только древовидную иерархию (через символические ссылки). Однако, чтобы получить содержимое файла, необходимо выполнить второй шаг после извлечения / нажатия, например:

$ git annex add mybigfile
$ git commit -m'add mybigfile'
$ git push myremote
$ git annex copy --to myremote mybigfile ## This command copies the actual content to myremote
$ git annex drop mybigfile ## Remove content from local repo
...
$ git annex get mybigfile ## Retrieve the content
## or to specify the remote from which to get:
$ git annex copy --from myremote mybigfile

Доступно много команд, и на сайте есть отличная документация. Пакет доступен на Debian .

177 голосов
/ 12 февраля 2009

Если программа не работает без файлов, кажется, что разбивать их на отдельные репозитории - плохая идея. У нас есть большие тестовые наборы, которые мы разбиваем на отдельные репозитории, но это действительно «вспомогательные» файлы.

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

Вот хорошее введение в подмодули из Git Book.

45 голосов
/ 09 апреля 2015

Другое решение, с апреля 2015 года: Хранилище больших файлов Git (LFS) (от GitHub).

Он использует git-lfs (см. git-lfs.github.com ) и протестирован с сервером, поддерживающим его: LFS-тест-сервер
Вы можете хранить метаданные только в git-репо, а большой файл - в другом месте.

https://cloud.githubusercontent.com/assets/1319791/7051226/c4570828-ddf4-11e4-87eb-8fc165e5ece4.gif

30 голосов
/ 22 марта 2011

Взгляните на git bup , который является расширением Git для разумного хранения больших двоичных файлов в репозитории Git.

Вы хотели бы иметь его в качестве подмодуля, но вам не придется беспокоиться о том, что хранилище будет трудно обрабатывать. Один из примеров их использования - хранение образов виртуальных машин в Git.

На самом деле я не видел лучших коэффициентов сжатия, но в моих репозиториях нет действительно больших двоичных файлов.

Ваш пробег может отличаться.

27 голосов
/ 26 сентября 2013

Вы также можете использовать мерзавец . Мне нравится, что это зависит только от акций Python и rsync. Он также поддерживает обычный рабочий процесс Git со следующими понятными командами:

git fat init
git fat push
git fat pull

Кроме того, вам необходимо зарегистрировать файл .gitfat в своем хранилище и изменить свои .gitattributes, указав расширения файлов, которыми вы хотите git fat управлять.

Вы добавляете двоичный файл, используя обычный git add, который, в свою очередь, вызывает git fat в соответствии с вашими правилами gitattributes.

Наконец, у него есть преимущество в том, что место, где на самом деле хранятся ваши двоичные файлы, может совместно использоваться репозиториями и пользователями и поддерживает все, что rsync делает.

ОБНОВЛЕНИЕ: не используйте git-fat, если вы используете мост Git-SVN. Это приведет к удалению двоичных файлов из вашего хранилища Subversion. Однако, если вы используете чистый Git-репозиторий, он прекрасно работает.

25 голосов
/ 12 февраля 2009

Я бы использовал подмодули (как Pat Notz) или два разных репозитория. Если вы слишком часто изменяете свои двоичные файлы, я постараюсь свести к минимуму влияние огромного хранилища, очищающего историю:

У меня была очень похожая проблема несколько месяцев назад: ~ 21 ГБ MP3-файлов, неклассифицированных (плохие имена, плохие id3, не знаю, нравится ли мне этот MP3-файл или нет ...) и реплицированных на трех компьютерах .

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

В итоге у меня было всего ~ 6 ГБ файлов MP3 и ~ 83 ГБ в каталоге .git. Я использовал git-write-tree и git-commit-tree для создания нового коммита без предков коммитов и начал новую ветку, указывающую на этот коммит. «Журнал Git» для этой ветви показал только один коммит.

Затем я удалил старую ветку, сохранил только новую ветку, удалил ref-logs и запустил «git prune»: после этого мои папки .git весили всего ~ 6 ГБ ...

Вы можете время от времени «очищать» огромное хранилище одним и тем же способом: ваш «мерзавец» будет быстрее.

12 голосов
/ 12 февраля 2009

По моему мнению, если вы, вероятно, будете часто изменять эти большие файлы, или если вы намереваетесь сделать много git clone или git checkout, то вам следует серьезно подумать об использовании другого Git-репозитория (или, возможно, другого способа для доступа к этим файлам).

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

11 голосов
/ 13 июля 2015

Решение, которое я хотел бы предложить, основано на ветвях-сиротах и ​​небольшом злоупотреблении механизмом тегов, далее именуемом * Двоичное хранилище тегов-сирот (OTABS)

TL; DR 12-01-2017 Если вы можете использовать LFS github или какую-либо другую стороннюю компанию, во что бы то ни стало, вам следует. Если не можете, тогда читайте дальше. Имейте в виду, это решение взломано и должно рассматриваться как таковое.

Желательные свойства ОТАБС

  • это решение pure git и git only - оно выполняет свою работу без какого-либо стороннего программного обеспечения (например, git-annex) или сторонней инфраструктуры (например, LFS на github). ).
  • эффективно хранит двоичные файлы , т. Е. Не раздувает историю вашего хранилища.
  • git pull и git fetch, включая git fetch --all, по-прежнему с эффективностью полосы пропускания , т. Е. По умолчанию не все большие двоичные файлы извлекаются из пульта.
  • работает на Windows .
  • хранит все в одном git-репозитории .
  • позволяет удалять устаревших двоичных файлов (в отличие от bup).

Нежелательные свойства ОТАБС

  • делает git clone потенциально неэффективным (но не обязательно, в зависимости от вашего использования). При развертывании этого решения вам, возможно, придется посоветовать коллегам использовать git clone -b master --single-branch <url> вместо git clone. Это потому, что git clone по умолчанию буквально клонирует весь репозиторий, включая вещи, на которые вы обычно не хотите тратить свою пропускную способность, например, нефиксированные коммиты. Взято из SO 4811434 .
  • делает пропускную способность git fetch <remote> --tags неэффективной, но не обязательно неэффективной для хранения. Вы всегда можете посоветовать своим коллегам не использовать его.
  • вам придется периодически использовать трюк git gc для очистки вашего хранилища от любых файлов, которые вам больше не нужны.
  • это не так эффективно, как bup или git-bigfiles . Но это соответственно больше подходит для того, что вы пытаетесь сделать, и больше готово. Вы, вероятно, столкнетесь с проблемами, связанными с сотнями тысяч небольших файлов или файлами размером в гигабайты, но читайте дальше для обходных путей.

Добавление двоичных файлов

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

  1. Создать новую сиротскую ветвь. git checkout --orphan binaryStuff сделает свое дело. В результате получается ветвь, которая полностью отключена от любой другой ветки, и первый коммит, который вы сделаете в этой ветке, не будет иметь родителя, что сделает его корневым.
  2. Очистите свой индекс, используя git rm --cached * .gitignore.
  3. Сделайте глубокий вдох и удалите все рабочее дерево, используя rm -fr * .gitignore. Внутренний каталог .git останется нетронутым, поскольку подстановочный знак * ему не соответствует.
  4. Скопируйте в свой VeryBigBinary.exe или VeryHeavyDirectory /.
  5. Добавьте и&& зафиксируйте.
  6. Теперь все становится сложнее - если вы вставите его в пульт как ветку, все ваши разработчики загрузят его в следующий раз, когда они вызовут git fetch, забив свое соединение. Вы можете избежать этого, нажав метку вместо ветки. Это все еще может повлиять на пропускную способность вашего коллеги и хранилище файловой системы, если они имеют привычку набирать git fetch <remote> --tags, но читайте дальше, чтобы обойти это. Иди и git tag 1.0.0bin
  7. Нажми свою сиротскую метку git push <remote> 1.0.0bin.
  8. Точно так, что вы никогда не нажмете свою ветку двоичных файлов случайно, вы можете удалить ее git branch -D binaryStuff. Ваш коммит не будет помечен для сборки мусора, потому что для его поддержки достаточно тега-сироты, указывающего на него 1.0.0bin.

Проверка двоичного файла

  1. Как я (или мои коллеги) извлекаю VeryBigBinary.exe в текущее рабочее дерево? Если ваша текущая рабочая ветка, например, master, вы можете просто git checkout 1.0.0bin -- VeryBigBinary.exe.
  2. Это не удастся, если у вас не загружен потерянный тег 1.0.0bin, в этом случае вам придется заранее git fetch <remote> 1.0.0bin.
  3. Вы можете добавить VeryBigBinary.exe в .gitignore вашего мастера, чтобы никто в вашей команде не загрязнил основную историю проекта двоичным файлом.

Полное удаление двоичного файла

Если вы решите полностью удалить VeryBigBinary.exe из своего локального хранилища, своего удаленного хранилища и хранилищ вашего коллеги, вы можете просто:

  1. Удалить потерянный тег на пульте git push <remote> :refs/tags/1.0.0bin
  2. Локальное удаление тега-сироты (удаляет все остальные теги, на которые нет ссылок) git tag -l | xargs git tag -d && git fetch --tags. Взято из SO 1841341 с небольшими изменениями.
  3. Используйте хитрость git gc, чтобы удалить ваш теперь не имеющий ссылки коммит локально. git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc "$@". Это также удалит все другие не связанные ссылки. Взято из SO 1904860
  4. Если возможно, повторите трюк с git gc на пульте. Это возможно, если вы самостоятельно размещаете свой репозиторий, и это может быть невозможно с некоторыми провайдерами git, такими как github или в некоторых корпоративных средах. Если вы пользуетесь хостингом у провайдера, который не предоставляет доступ по ssh к удаленному, просто оставьте его. Вполне возможно, что инфраструктура вашего провайдера очистит вашу ссылку без привязки в свое приятное время. Если вы находитесь в корпоративной среде, вы можете посоветовать своим ИТ-специалистам запускать мусорное задание cron, собирая ваш пульт один раз в неделю или около того. Независимо от того, влияют они или нет, это не повлияет на вашу команду с точки зрения пропускной способности и хранилища, если вы советуете своим коллегам всегда git clone -b master --single-branch <url> вместо git clone.
  5. Всем вашим коллегам, которые хотят избавиться от устаревших тегов-сирот, нужно только применить шаги 2-3.
  6. Затем можно повторить шаги 1-8 из Добавление двоичных файлов , чтобы создать новый потерянный тег 2.0.0bin. Если вы беспокоитесь о том, что ваши коллеги набирают git fetch <remote> --tags, вы можете назвать его еще раз 1.0.0bin. Это будет гарантировать, что в следующий раз, когда они выберут все теги, старый 1.0.0bin не будет иметь ссылки и помечен для последующей сборки мусора (с помощью шага 3). Когда вы пытаетесь перезаписать тег на пульте, вы должны использовать -f, например: git push -f <remote> <tagname>

Послесловие

  • OTABS не касается вашего мастера или любых других исходных кодов / ветвей разработки. Хеши коммитов, вся история и небольшой размер этих веток не затрагиваются. Если вы уже раздули свою историю исходного кода с помощью двоичных файлов, вам придется очистить ее как отдельную часть работы. Этот скрипт может быть полезен.

  • Подтверждено для работы в Windows с git-bash.

  • Рекомендуется применить набор стандартных трюков , чтобы сделать хранение бинарных файлов более эффективным. Частое выполнение git gc (без каких-либо дополнительных аргументов) позволяет git оптимизировать базовое хранилище ваших файлов с помощью двоичных дельт. Однако, если ваши файлы вряд ли останутся похожими на коммит, вы можете полностью отключить двоичные дельты. Кроме того, поскольку нет смысла сжимать уже сжатые или зашифрованные файлы, такие как .zip, .jpg или .crypt, git позволяет отключить сжатие основного хранилища. К сожалению, это параметр «все или ничего», влияющий и на ваш исходный код.

  • Возможно, вы захотите написать сценарии частей OTABS, чтобы обеспечить более быстрое использование. В частности, сценарии 2-3 из Полное удаление бинарных файлов в update ловушку git могут дать убедительную, но, возможно, опасную семантику для git fetch («извлекать и удалять все, что устарело») .

  • Возможно, вы захотите пропустить шаг 4 из Полное удаление двоичных файлов , чтобы сохранить полную историю всех двоичных изменений на пульте дистанционного управления за счет увеличения объема центрального хранилища. Локальные хранилища со временем останутся сухими.

  • В мире Java можно объединить это решение с maven --offline, чтобы создать воспроизводимую автономную сборку, полностью сохраненную в вашем контроле версий (это проще с maven, чем с gradle). В мире Голанга возможно использовать это решение для управления GOPATH вместо go get. В мире Python это можно комбинировать с virtualenv для создания автономной среды разработки, не полагаясь на серверы PyPi для каждой сборки с нуля.

  • Если ваши двоичные файлы меняются очень часто, например, артефакты сборки, было бы неплохо написать сценарий решения, в котором 5 последних версий артефактов будут храниться в потерянных тегах monday_bin, tuesday_bin,. .., friday_bin, а также потерянный тег для каждого выпуска 1.7.8bin 2.0.0bin и т. Д. Вы можете вращать weekday_bin и удалять старые двоичные файлы ежедневно. Таким образом, вы получаете лучшее из двух миров: вы сохраняете всю историю вашего исходного кода, но только релевантную историю ваших двоичных зависимостей. Также очень легко получить двоичные файлы для данного тега без получения всего исходного кода со всей его историей: git init && git remote add <name> <url> && git fetch <name> <tag> должен сделать это за вас.

9 голосов
/ 03 октября 2010

SVN, кажется, обрабатывает двоичные дельты более эффективно, чем Git.

Мне пришлось выбрать систему управления версиями для документации (файлы JPEG, файлы PDF и файлы .odt). Я только что протестировал добавление файла JPEG и поворот его на 90 градусов четыре раза (чтобы проверить эффективность двоичных дельт). Репозиторий Git вырос на 400%. Репозиторий SVN вырос только на 11%.

Похоже, что SVN намного эффективнее с двоичными файлами.

Поэтому я выбрал Git для исходного кода и SVN для бинарных файлов, таких как документация.

2 голосов
/ 10 сентября 2017

Я ищу мнения о том, как обрабатывать большие двоичные файлы, от которых зависит мой исходный код (веб-приложение). Что вы думаете об этом?

Я лично столкнулся с ошибками синхронизации с Git с некоторыми из моих облачных хостов, как только двоичные данные моих веб-приложений зарезались выше отметки 3 ГБ . В то время я считал BFT Repo Cleaner , но это было похоже на взлом. С тех пор я начал просто хранить файлы вне сферы действия Git, вместо этого используя специализированные инструменты , такие как Amazon S3, для управления файлами, управления версиями и резервного копирования.

Кто-нибудь имеет опыт работы с несколькими репозиториями Git и управления ими в одном проекте?

Да. Темы Гюго в основном управляются таким образом. Это немного круто, но это делает работу.


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

.

Дополнительные опции для рассмотрения включают Minio и s3cmd .

...