Решение, которое я хотел бы предложить, основано на бесхозных ветвях и небольшом злоупотреблении механизмом тегов, далее именуемым * Бинарное хранилище бесхозных тегов (OTABS).
TL; DR 12-01-2017 Если вы можете использовать GFS от Github или какой-либо другой третьей стороны, во что бы то ни стало, вам следует. Если не можете, тогда читайте дальше. Имейте в виду, это решение является взломом и должно рассматриваться как таковое.
Желательные свойства ОТАБС
- это чисто решение git and 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 и т. Д.) На случай, если произойдет какое-либо бедствие.
- Создать новую сиротскую ветку.
git checkout --orphan binaryStuff
сделает свое дело. Это создает ветку, которая полностью отключена от любой другой ветви, и первый коммит, который вы сделаете в этой ветке, не будет иметь родителя, что сделает его корневым.
- Очистите свой индекс, используя
git rm --cached * .gitignore
.
- Сделайте глубокий вдох и удалите все рабочее дерево, используя
rm -fr * .gitignore
. Внутренний .git
каталог останется нетронутым, потому что *
подстановочный знак не соответствует ему.
- Скопируйте в свой VeryBigBinary.exe или в свой каталог VeryHeavyDirectory /.
- Добавьте это && зафиксируйте это.
- Теперь это становится сложнее - если вы вставите его в удаленную ветвь как ветвь, все ваши разработчики загрузят его в следующий раз, когда они вызовут
git fetch
засорение своего соединения. Вы можете избежать этого, нажав метку вместо ветки. Это все еще может повлиять на пропускную способность вашего коллеги и хранилище файловой системы, если они имеют привычку печатать git fetch <remote> --tags
, но читайте дальше, чтобы обойти это. Идти вперед иgit tag 1.0.0bin
- Нажмите свой тег сироты
git push <remote> 1.0.0bin
.
- Точно так же, что вы никогда не нажмете свою бинарную ветку случайно, вы можете удалить ее
git branch -D binaryStuff
. Ваш коммит не будет помечен для сборки мусора, потому что на него 1.0.0bin
достаточно пустого тега, указывающего на него .
Проверка двоичного файла
- Как я (или мои коллеги) извлекаю VeryBigBinary.exe в текущее рабочее дерево? Если ваша текущая рабочая ветка, например, master, вы можете просто
git checkout 1.0.0bin -- VeryBigBinary.exe
.
- Это не удастся, если у вас нет
1.0.0bin
загруженного тега-сироты , в этом случае вам придется сделать это git fetch <remote> 1.0.0bin
заранее.
- Вы можете добавить его к
VeryBigBinary.exe
своему мастеру .gitignore
, чтобы никто в вашей команде не загрязнил основную историю проекта двоичным файлом.
Полное удаление двоичного файла
Если вы решите полностью удалить VeryBigBinary.exe из локального хранилища, удаленного хранилища и хранилищ вашего коллеги, вы можете просто:
- Удалить потерянный тег на пульте
git push <remote> :refs/tags/1.0.0bin
- Удалить потерянный тег локально (удаляет все остальные теги, на которые нет ссылок)
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 "$@"
, Это также удалит все другие не связанные ссылки. Взято из 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 не касается вашего мастера или любых других исходных кодов / веток разработки. Хеши коммитов, вся история и небольшой размер этих веток не затрагиваются. Если вы уже раздули свою историю исходного кода с помощью двоичных файлов, вам придется очистить ее как отдельную часть работы. Этот скрипт может быть полезен.
Подтвердили работу на 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>
следует сделать за вас.