Возможно ли сохранить файл без вершин в репозитории git
Вот проблема:
Я создал голый репозиторий git на моем месте партнера-партнера, который я использую в качестве ссылочного репозитория со всех местоположений/компьютеров, на которых я поддерживаю свой проект.
Дело в том, что в моем проекте используется файл sqlite db, который постоянно растет (сейчас он составляет около 150 МБ).
По прошествии времени моя папка .git становится все больше и больше (в последнее время около 1 ГБ). И мое пространство для хостинга ограничено.
Мне нужен голый репозиторий, содержащий HEAD-версию этого файла db, но мне действительно не нужно сохранять историю его версий.
Итак, чтобы получить некоторое пространство, время от времени я удаляю db файл из истории, очищаю репозиторий и воссоздаю голую версию. Это работает, но это довольно боль.
Есть ли способ сообщить git сохранить только последнюю версию файла и удалить его историю?
Ответы
Ответ 1
Короткий ответ: нет.
Более полезный ответ: Git не отслеживает файлы по отдельности, поэтому попросить его выбросить историю одного файла означает, что он должен будет полностью переписать всю свою историю на каждую фиксацию, и это приведет к все виды уродливых проблем.
Вы можете сохранить файл в аннотированном теге, но это не очень удобно. В основном это происходит следующим образом:
ID=`git hash-object -w yourfile.sqlite`
git tag -a -m "Tag database file" mytag $ID
Никоим образом это не удобно обновлять (или даже создавать) файл базы данных в рабочем дереве для вас... вам нужно будет использовать скрипты hook для имитации этого.
Полное раскрытие: я не совсем уверен, действительно ли можно нажимать метки, которые не покрываются обычной историей. Я подозреваю, что это не так, и в этом случае этот рецепт был бы намного менее полезным.
Ответ 2
Похоже, вы ищете решение неправильной проблемы.
Большие двоичные файлы часто нужно хранить в репозиториях, но я не думаю, что база данных SQLite - это то, что вам действительно нужно хранить в своей двоичной форме в репозитории.
Скорее, вы должны сохранить схему в управлении версиями, и если вам тоже нужно хранить данные, сериализуйте ее (в XML, JSON, YAML...) и версию тоже. Конструкция script может создавать базу данных и при необходимости деактивировать данные в ней.
Поскольку текстовый формат сериализации можно эффективно отслеживать с помощью Git, вы не будете беспокоиться о нехватке места для хранения прошлых версий, даже если вы не думаете, что вам нужен доступ к ним.
Ответ 3
Вы всегда можете использовать конфигурационный файл .gitignore
для этого - с самого начала.
И... (из эта тема: kudos для Björn Steinbrink!)
Использовать фильтр-ветку, чтобы отбросить родителей на первой фиксации, которую вы хотите сохранить, а затем отбросить старый рывок.
Скажем, $drop
является хешем последняя фиксация, которую вы хотите сбросить. к держите вещи здравомыслящими и простыми, убедитесь, что первая фиксация, которую вы хотите сохранить, то есть. ребенок $drop
, не является слиянием совершить. Затем вы можете использовать:
git filter-branch --parent-filter "sed -e 's/-p $drop//'" \
--tag-name-filter cat -- \
--all ^$drop
Вышеизложенное переписывает родителей всех совершает то, что приходит после "$drop
.
Проверьте результаты с помощью gitk.
Затем, чтобы очистить весь старый рывок.
Во-первых, резервные ссылки из Фильтрация:
git for-each-ref --format='%(refname)'refs/original | \
while read ref
do
git update-ref -d "$ref"
done
Затем очистите свои логги:
git reflog expire --expire=0 --all
И, наконец, переупаковать и отбросить все старые недостижимые объекты: git repack -ad git prune # Для объектов, которые repack -ad может оставить около
В этот момент все, что ведет до и включая $drop должно быть ушел.
Ответ 4
Если я понимаю ваш вопрос, я думаю, что у меня есть простое решение.
- Сначала создайте резервную копию файла,
- Удалить его из рабочего дерева/дерева. Не git rm, просто rm.
- Сделайте фиксацию.
- Убедитесь, что файл добавлен в .gitignore.
При последующих коммитах git больше не будет пытаться добавить этот файл. Обратите внимание, что у вас все еще будет файл, сохраненный в предыдущих фиксациях. Это просто, что вы не будете добавлять его к каждой фиксации, которую вы совершаете в будущем. Чтобы удалить его из предыдущих коммитов, вам понадобится совет от кого-то, у кого больше опыта git, чем у меня.
Ответ 5
Добавьте sqlite.db в свой .gitignore.
Чтобы проверить текущий db для (потенциального) нажатия текущей ветвью:
branch="$(sed 's,.*refs/heads/,,' "$(git rev-parse --git-dir)"/HEAD)"
objectname=$(git hash_object -w "$(git rev-parse --show-toplevel)/sqlite.db")
git tag -f db_heads/$branch $objectname
при нажатии ветки:
git push origin $branch +db_heads/$branch
При извлечении ветки:
git fetch origin $branch tags/db_heads/$branch:tags/db_heads/$branch
при проверке ветки:
git checkout $branch
git cat-file -p db_heads/$branch >"$(git rev-parse --show_toplevel)/sqlite.db"
И это должно сделать это, я думаю.