2010-02-12 4 views
16

Вот проблема:Можно ли сохранить неверсионный файл в репозитории

Я создал голый репозиторий на моем хостинге-партнер место, которое я использую в качестве справочного хранилища из всех мест/компьютеров I поддерживают мой проект.

Дело в том, что мой проект использует файл sqlite db, который постоянно растет (он составляет около 150 МБ). По прошествии времени моя папка .git становится все больше и больше (в последнее время около 1 ГБ). И мое пространство для хостинга ограничено.

Мне нужно, чтобы голый репозиторий содержал версию HEAD этого файла db, но мне действительно не нужно сохранять историю его версий.

Итак, чтобы получить некоторое пространство, время от времени я удаляю db-файл из истории, очищаю репозиторий и воссоздаю голую версию. Это работает, но это довольно боль.

Есть ли способ сказать git сохранить только последнюю версию файла и удалить его историю?

+1

вопрос, связанный с этим: http://stackoverflow.com/questions/540535/managing-large-binary-files-with-git – jfs

+0

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

+0

Зачем вам этот файл db, чтобы сохранить копию схемы или данных? Или оба? –

ответ

5

Короткий ответ: нет.

Более полезный ответ: Git не отслеживает файлы по отдельности, поэтому попросить его выбросить историю одного файла означало бы, что он должен будет полностью переписать всю свою историю на каждую фиксацию, а это приведет ко всем виды уродливых проблем.

Вы можете сохранить файл в аннотированном теге, но это не очень удобно. Это в основном идет как это:

ID=`git hash-object -w yourfile.sqlite` 
git tag -a -m "Tag database file" mytag $ID 

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

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

3

Для этого вы всегда можете использовать конфигурационный файл .gitignore - с самого начала.

И ... (от this thread: престижность для Бьерна 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 

Затем очистить ваши reflogs:

git reflog expire --expire=0 --all 

И, наконец, упакуйте и удалить все старые недостижимые объекты: мерзавец набивку -ad git prune # Для объектов, которые repack -ad, возможно, оставил около

В этот момент каждый вещь, ведущая вверх до и включая $ drop должна быть ушла.

+0

Я ищу решение, которое * хранит * копию db в репозитории –

+0

Затем вы можете создать скрипт, который удаляет историю после каждой фиксации. –

4

Похоже, вы ищете решение проблемы.

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

Скорее, вы должны сохранить схему в управлении версиями, и если вам тоже нужно хранить данные, ее сериализуйте (в XML, JSON, YAML ...) и версию. Сценарий сборки может создавать базу данных и при необходимости деактивировать данные.

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

+0

Таким образом, git может применять свои обычные сжатия и различные методы, делая это гораздо менее болезненным. Единственное, на что нужно позаботиться, - это создать правильно отсортированный формат сериализации, который минимизирует размер diff. –

+0

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

+0

Это классная идея ... есть ли у вас любимый скрипт для сериализации на основе текста? – AlexMA

0

Если я понимаю ваш вопрос, я думаю, что у меня есть простое решение.

  1. Первый резервный файл где-то,
  2. Удалить его из рабочего дир/дерево. Не git rm, просто rm.
  3. Сделайте фиксацию.
  4. Убедитесь, что файл добавлен в .gitignore.

При последующих коммитах GIT больше не будет пытаться добавить этот файл. Обратите внимание, что у вас все еще будет файл, сохраненный в предыдущих фиксациях. Просто вы не будете добавлять его к каждой фиксации, которую вы делаете в будущем. Чтобы удалить его из предыдущих коммитов, вам понадобится совет от кого-то, у кого больше опыта GIT, чем у меня.

0

Добавьте sqlite.db в свой .gitignore.

Для регистрации в текущей БД для (потенциала) толкающего с текущей ветви:

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" 

И это должно сделать это, я думаю.