Свертывание истории git-репозитория - PullRequest
79 голосов
/ 30 октября 2008

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

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

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

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

1-----2-----3-----4-----+---+---+
                   \       /
                    +-----+---+---+
  1. Хранилище создано
  2. Добавлен большой набор бинарных файлов
  3. Удален большой набор двоичных файлов
  4. Новый предполагаемый «запуск» хранилища

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

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

Ответы [ 4 ]

87 голосов
/ 31 октября 2008

Вы можете удалить двоичный раздув и сохранить всю свою историю. 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                      

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

26 голосов
/ 24 января 2009

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

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

20 голосов
/ 30 октября 2008

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

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

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

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

5 голосов
/ 30 октября 2008

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).
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...