31

У меня есть git repo с очень большими двоичными файлами. Мне они больше не нужны, и я не забочусь о том, чтобы проверить файлы с более ранних коммитов. Итак, чтобы уменьшить размер репо, я хочу полностью удалить двоичные файлы из истории.Обновите команду разработчиков с переписанной историей Git repo, удалив большие файлы

После веб-поиска, я пришел к выводу, что мой лучший (только?) Вариант заключается в использовании git-filter-branch:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch big_1.zip big_2.zip etc.zip' HEAD 

это, кажется ли, как хороший подход до сих пор?

Предполагая, что да, у меня есть еще одна проблема, с которой можно бороться. git manual has this warning:

ВНИМАНИЕ! Переписанная история будет иметь разные имена объектов для всех объектов и не будет сходиться с исходной ветвью. Вы не сможете легко нажимать и распространять переписанную ветку поверх исходной ветви. Пожалуйста, не используйте эту команду, если вы не знаете о всех последствиях, и избегайте ее использования в любом случае, если достаточно простой фиксации, чтобы исправить вашу проблему. (Смотрите раздел «Восстановление с верховьев перебазироваться» в GIT-перебазирования (1) для получения дополнительной информации о перезаписи опубликованной истории.)

У нас есть удаленный репозиторий на нашем сервере. Каждый разработчик подталкивает и извлекает из него. Основываясь на вышеприведенном предупреждении (и мое понимание того, как работает git-filter-branch), я не думаю, что смогу запустить git-filter-branch на моей локальной копии, а затем нажимать изменения.

Итак, я предварительно планирую пройти следующие шаги:

  1. Скажите все мои разработчик совершить, толчок, и прекратить работу на некоторое время.
  2. Войдите в систему и запустите фильтр на центральном репо.
  3. Попросите всех удалить свои старые копии и снова клонировать с сервера.

Звучит это правильно? Это лучшее решение?

+2

Это происходит для меня теперь, что * простой * вещь, чтобы сделать может быть, чтобы ваши разработчики каждом запуске идентичная команда 'git-filter-branch'. Они должны заканчиваться историями, идентичными тем, что вы произвели, без повторного клонирования или переустановки вручную. –

+1

@BenJackson файлы кода будут идентичными, но объекты commit будут иметь разные метаданные коммиттера, добавленные rebase. – Douglas

+1

@Douglas Я не думаю, что 'git filter-branch' изменяет данные коммиттера, если вы явно не попросите его об этом. ('git commit -rebase' делает, но не' git filter-branch', насколько я могу видеть.) – cdhowie

ответ

18

Да, ваше решение будет работать. У вас также есть другой вариант: вместо этого на центральном репо, запустите фильтр на вашем клоне, а затем нажмите его обратно с git push --force --all. Это заставит сервер принимать новые ветки из вашего репозитория. Это заменяет только шаг 2; другие шаги будут одинаковыми.

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

+0

Это не учитывает все случаи. Если есть теги или другие ветви, вы должны все '--tag-name-filter cat' и' - --all' вместо HEAD использовать опции ветвления фильтра git. См. Мой ответ для получения дополнительной информации. –

5

Если вы не хотите, чтобы ваши разработчики повторно клонировали, вероятно, им удастся перетащить большие файлы. Например, если они тщательно сплайсируют новую историю, которую вы создадите, а затем произойдете с git merge из локальная ветка проекта, которая не была переустановлена, родители слияния будут включать ветку проекта, которая в конечном итоге указывает на всю историю, которую вы удалили с git filter-branch.

+0

Так, другими словами, мой план, чтобы каждый повторный клон избежал много потенциальных ошибок? – rlkw1024

+1

Для вас и репозитория.Это будет раздражать любого, у кого есть уже существующая коллекция ветвей и закладок проекта. –

9

Ваш план хорош (хотя лучше было бы выполнять фильтрацию на голой клоне вашего репозитория, а не на центральном сервере), но, кроме git-filter-branch, вы должны использовать мою BFG Repo-Cleaner, более быструю и удобную альтернативу до git-filter-branch, предназначенный специально для удаления больших файлов от Git repos.

Скачать the Java jar (требуется Java 6 или выше) и выполните следующую команду:

$ java -jar bfg.jar --strip-blobs-bigger-than 1MB my-repo.git 

Любые блобы более 1 МБ (то есть не в вашем последнего фиксации) будет полностью удален из историю вашего хранилища. Затем вы можете использовать git gc очистить от мертвых данные:

$ git gc --prune=now --aggressive 

BFG обычно 10-50x быстрее, чем при запуске git-filter-branch и варианты с учетом вокруг этих двух общих сценариев использования:

  • Удаление Сумасшедшая большие файлы
  • Удаление паролей, учетные данные & другие Частные данные
3

Ваше решение не заполнено. Вы должны включить --tag-name-filter cat в качестве аргумента для фильтрации ветви, чтобы также изменились теги, которые содержат большие файлы. Вы также должны изменить все ссылки, а не только HEAD, поскольку фиксация может быть в нескольких ветвях.

Вот некоторые лучше код:

git filter-branch --index-filter 'git rm --cached --ignore-unmatch big_1.zip big_2.zip etc.zip' --tag-name-filter cat -- --all 

Github хорошее руководство: https://help.github.com/articles/remove-sensitive-data