Управление большими двоичными файлами с помощью Git

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

  • Скопируйте двоичные файлы вручную.
    • Pro: Не уверен.
    • Contra: Я категорически против этого, так как он увеличивает вероятность ошибок при настройке нового сайта/миграции старого. Создает еще одно препятствие.
  • Управлять их всеми с помощью Git.
    • Pro: удаляет возможность "забыть" для копирования важного файла
    • Contra: разворачивает репозиторий и уменьшает гибкость при управлении базой кода и проверками, клонами и т.д. займет довольно много времени.
  • Отдельные репозитории.
    • Pro: проверка/клонирование исходного кода выполняется быстро, и изображения правильно архивируются в собственном репозитории.
    • Contra: Удаляет простоту наличия единственного репозитория Git в проекте. Это, безусловно, представляет некоторые другие вещи, о которых я не думал.

Каковы ваши переживания/мысли относительно этого?

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

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

Ответ 1

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

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

Здесь хорошее введение в подмодули из Git Book.

Ответ 2

Недавно я обнаружил git-приложение, которое я считаю удивительным. Он был разработан для эффективного управления большими файлами. Я использую его для своих фото/музыки (и т.д.). Разработка 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.

Ответ 4

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

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

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

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

Ответ 5

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

git fat init
git fat push
git fat pull

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

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

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

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

Ответ 6

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

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

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

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

Затем я удалил старую ветку, сохранил только новую ветвь, удалил рефактории и запустил "git prune": после этого мои .git-папки весили только ~ 6 GB...

Вы можете "продувать" огромное хранилище время от времени таким же образом: ваш "git клон" будет быстрее.

Ответ 7

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

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

Ответ 8

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

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

Желательные свойства OTABS

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

Нежелательные свойства OTABS

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

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

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

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

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

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

Полностью удаляет двоичный файл

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

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

Послесловие

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

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

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

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

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

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

  • Если ваши двоичные файлы очень часто меняются, например, сбор артефактов, может быть хорошей идеей для script решения, которое хранит 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

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

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

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

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

Ответ 10

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

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

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

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


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

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

Ответ 11

git clone --filter из Git 2.19 + мелкие клоны

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

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

При этом мы могли бы сначала сделать неглубокое клонирование, а затем автоматизировать, какие двоичные объекты следует выбирать с помощью системы сборки для каждого типа сборки.

Уже существует --filter=blob:limit<size> который позволяет ограничить максимальный размер --filter=blob:limit<size> для выборки.

Я представил минимальный подробный пример того, как выглядит эта функция: Как мне клонировать только подкаталог репозитория Git?

Ответ 12

Посмотрите camlistore. На самом деле это не на самом деле Git, но я считаю более подходящим то, что вам нужно делать.