2008-10-30 3 views
79

У нас есть проект git, который имеет довольно большую историю.Свертывание истории хранилища git

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

Однако размер нашего репозитория составляет> 200 МБ (общая проверка в настоящее время составляет ~ 20 МБ) из-за того, что эти файлы были ранее зафиксированы.

Что нам нужно сделать, так это «свернуть» историю, чтобы репозиторий был создан из более поздней версии, чем был. Например

1-----2-----3-----4-----+---+---+ 
        \  /
        +-----+---+---+ 
  1. Repository создано
  2. Большой набор бинарных файлов, добавляемых
  3. Большой набор бинарных файлов удалены
  4. Новый предполагаемый 'старт' репозитария

Так эффективно мы хотите потерять историю проекта до определенного момента. На данный момент существует только одна ветка, поэтому нет сложностей с попыткой иметь дело с несколькими стартовыми точками и т. Д. Однако мы не хотим потерять всю историю и запустить новый репозиторий с текущей версией.

Возможно ли это, или мы обречены иметь раздутый хранилище навсегда?

ответ

88

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

$ git log --stat  # list all commits and commit messages 

Поиск это для фиксаций, что добавлять и удалять двоичные файлы и отметить их SHA1s, скажем 2bcdef и 3cdef3.

Затем, чтобы отредактировать историю репо, используйте команду rebase -i с ее интерактивной опцией, начиная с родителя комманды, где вы добавили свои двоичные файлы.Это запустит ваш $ EDITOR, и вы увидите список фиксаций, начиная с 2bcdef:

$ git rebase -i 2bcdef^ # generate a pick list of all commits starting with 2bcdef 
# Rebasing zzzzzz onto yyyyyyy 
# 
# Commands: 
# pick = use commit 
# edit = use commit, but stop for amending 
# squash = use commit, but meld into previous commit 
# 
# If you remove a line here THAT COMMIT WILL BE LOST. 
# 
pick 2bcdef Add binary files and other edits 
pick xxxxxx Another change 
    . 
    . 
pick 3cdef3 Remove binary files; link to them as external resources 
    . 
    . 

Вставьте squash 3cdef3 как второй строки и удалить строку, которая говорит pick 3cdef3 из списка. Теперь у вас есть список действий для интерактивного rebase, который объединит коммиты, которые добавляют и удаляют ваши двоичные файлы в один коммит, diff - это просто любые другие изменения этих коммитов. Тогда это будет повторно все последующие фиксаций в порядке, когда вы говорите, что для завершения:

$ git rebase --continue 

Это займет минуту или две.
Теперь у вас есть репо, которое больше не имеет двоичных файлов, идущих или идущих. Но они по-прежнему занимают место, потому что, по умолчанию, Git сохраняет изменения в течение 30 дней, прежде чем они могут быть собраны в мусор, чтобы вы могли передумать. Если вы хотите, чтобы удалить их сейчас:

$ git reflog expire --expire=1.minute refs/heads/master 
     #all deletions up to 1 minute ago available to be garbage-collected 
$ git fsck --unreachable  # lists all the blobs(files) that will be garbage-collected 
$ git prune 
$ git gc      

Теперь вы удалили навороты, но сохранили остальную часть истории.

+1

Хорошо и ответит. – JesperE 2008-11-02 17:01:10

+7

Вам просто нужно помнить, что другие люди уже вытащили из этого хранилища, переписывая историю, это путает их тягу. В руководстве git-rebase объясняется, как восстановить эти другие репозитории. http://www.kernel.org/pub/software/scm/git/docs/git-rebase.html – Otto 2009-01-24 16:26:17

6

git-fast-export Что вы ищете?

NAME 
    git-fast-export - Git data exporter 

SYNOPSIS 
    git-fast-export [options] | git-fast-import 

DESCRIPTION 
    This program dumps the given revisions in a form suitable to be piped into git-fast- 
    import(1). 

    You can use it as a human readable bundle replacement (see git-bundle(1)), or as a kind 
    of an interactive git-filter-branch(1). 
21

Благодаря сообщению JesperE, я посмотрел в git-filter-branch - что может быть на самом деле то, что вы хотите. Похоже, что вы могли сохранить свои прежние коммиты, кроме того, что они будут изменены, так как ваши большие файлы были удалены. Из git-filter-branch man page:

Предположим, что вы хотите удалить файл (содержащий конфиденциальную информацию или нарушение авторских прав) от всех фиксаций:

мерзавец фильтр-филиал --tree-фильтр «гт имя_файла» ГОЛОВА

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

+2

Проверьте связь github ... имеет несколько мощных параметров с командой git-filter-branch: https://help.github.com/articles/remove-sensitive-data – ricosrealm 2013-01-09 05:31:30

25

Вы можете использовать git filter-branch с помощью трансплантатов, чтобы совершить число 4 фиксации нового корня вашей ветви. Просто создайте файл .git/info/grafts только с одной строкой в ​​нем, содержащей SHA1 коммиттерского номер 4.

Если теперь сделать git log или gitk вы увидите, что эти команды будут отображаться совершить номер 4 в корне вашей отрасли. Но ничего не изменилось бы в вашем репозитории. Вы можете удалить .git/info/grafts, а выход git log или gitk будет таким, как прежде. Чтобы на самом деле сделать фиксацию числа 4 новым корнем, вам нужно будет запустить git filter-branch без аргументов.

Смежные вопросы