Скрытие истории хранилища git

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

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

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

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

1-----2-----3-----4-----+---+---+
                   \       /
                    +-----+---+---+
  • Создан репозиторий
  • Добавлен большой набор добавленных двоичных файлов.
  • Удален большой набор бинарных файлов.
  • Новый предназначенный "запуск" репозитория

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

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

Ответ 1

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

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

Найти это для коммитов, которые добавляют и удаляют ваши двоичные файлы и отмечают их SHA1, например 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                      

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

Ответ 2

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

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

Ответ 3

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

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

git filter-branch --tree-filter 'rm filename' HEAD

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

Ответ 4

Является 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).