Как удалить не связанные ссылки из моего репозитория Git - PullRequest
104 голосов
/ 15 декабря 2009

У меня есть репозиторий GitHub с двумя ветками - master и release.

В ветке релиза содержались бинарные дистрибутивные файлы, которые способствовали очень большому размеру репо (> 250 МБ), поэтому я решил исправить ситуацию.

Сначала я удалил ветку удаленного выпуска через git push origin :release

Затем я удалил локальную ветку релиза. Сначала я попробовал git branch -d release, но git сказал "ошибка: ветвь 'release' не является предком вашей текущей HEAD." , что верно, поэтому я сделал git branch -D release, чтобы заставить его Исключен.

Но размер моего хранилища, как локально, так и на GitHub, все еще был огромен. Итак, я пробежался по обычному списку команд git, вроде git gc --prune=today --aggressive, без удачи.

Следуя инструкциям Чарльза Бейли в SO 1029969 , я смог получить список SHA1 для самых больших капель. Затем я использовал скрипт из SO 460331 , чтобы найти капли ... и пять самых больших не существуют, хотя более мелкие капли найдены, поэтому я знаю, что скрипт работает.

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

Ответы [ 10 ]

174 голосов
/ 06 февраля 2013

... и без лишних слов, могу ли я представить вам эту полезную команду "git-gc-all", гарантированно удаляющую all ваш git-мусор, пока они не могут вызвать дополнительные переменные конфигурации:

git -c gc.reflogExpire=0 -c gc.reflogExpireUnreachable=0 -c gc.rerereresolved=0 -c gc.rerereunresolved=0 -c gc.pruneExpire=now gc

Вам также может понадобиться сначала выполнить что-то вроде этого, о дорогой, мерзавец сложен !!

git remote rm origin
rm -rf .git/refs/original/ .git/refs/remotes/ .git/*_HEAD .git/logs/
git for-each-ref --format="%(refname)" refs/original/ | xargs -n1 --no-run-if-empty git update-ref -d

Вам также может понадобиться удалить некоторые теги, спасибо Zitrax:

git tag | xargs git tag -d

Я поместил все это в скрипт: git-gc-all-ferocious .

59 голосов
/ 23 марта 2015

Как описано здесь , просто используйте

git reflog expire --expire-unreachable=now --all
git gc --prune=now

git reflog expire --expire-unreachable=now --all удаляет все ссылки на недоступные коммиты в reflog.

git gc --prune=now удаляет коммиты сами.

Внимание : Только использование git gc --prune=now не будет работать, так как на эти коммиты все еще ссылаются в reflog. Поэтому очистка рефлога обязательна.

32 голосов
/ 15 декабря 2009

Как уже упоминалось в , этот ответ SO , git gc действительно может увеличить размер репо!

См. Также эту тему

Теперь в git есть механизм безопасности, позволяющий не удалять объекты без ссылок сразу при запуске 'git gc'.
По умолчанию объекты, на которые нет ссылок, хранятся в течение 2 недель. Это сделано для того, чтобы вам было легче восстанавливать случайно удаленные ветви или коммиты, или чтобы избежать гонки, в которой только что созданный объект в процессе, но еще не на который ссылаются, может быть удален процессом 'git gc', работающим параллельно .

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

В любом случае ... Чтобы решить вашу проблему, вам просто нужно запустить 'git gc' с аргументом --prune=now, чтобы отключить этот льготный период и сразу же избавиться от этих объектов, на которые нет ссылок (безопасно, только если нет других действий git происходят одновременно, что должно быть легко обеспечено на рабочей станции).

И кстати, используя 'git gc --aggressive' с более поздней версией git (или 'git repack -a -f -d --window=250 --depth=250')

В той же теме упоминается :

 git config pack.deltaCacheSize 1

Это ограничивает размер дельта-кэша одним байтом (фактически отключая его) вместо значения по умолчанию 0, что означает неограниченный. После этого я могу перепаковать этот репозиторий, используя указанную выше команду git repack в системе x86-64 с 4 ГБ оперативной памяти и с использованием 4 потоков (это четырехъядерное ядро). Использование резидентной памяти увеличивается почти до 3,3 ГБ.

Если ваша машина SMP и у вас недостаточно ОЗУ, вы можете уменьшить количество потоков только до одного:

git config pack.threads 1

Кроме того, вы можете дополнительно ограничить использование памяти с помощью --window-memory argument до 'git repack'.
Например, использование --window-memory=128M должно поддерживать разумную верхнюю границу дельты использование памяти поиска, хотя это может привести к менее оптимальному дельта-соответствию, если репо содержит много больших файлов.


В ответвлении фильтра вы можете рассмотреть (с осторожностью) этот скрипт

#!/bin/bash
set -o errexit

# Author: David Underhill
# Script to permanently delete files/folders from your git repository.  To use 
# it, cd to your repository's root and then run the script with a list of paths
# you want to delete, e.g., git-delete-history path1 path2

if [ $# -eq 0 ]; then
    exit 0
fi

# make sure we're at the root of git repo
if [ ! -d .git ]; then
    echo "Error: must run this script from the root of a git repository"
    exit 1
fi

# remove all paths passed as arguments from the history of the repo
files=$@
git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $files" HEAD

# remove the temporary history git-filter-branch otherwise leaves behind for a long time
rm -rf .git/refs/original/ && git reflog expire --all &&  git gc --aggressive --prune
18 голосов
/ 16 декабря 2009

git gc --prune=now или низкий уровень git prune --expire now.

12 голосов
/ 18 декабря 2009

Каждый раз, когда движется ваша ГОЛОВА, git отслеживает это в reflog. Если вы удалили коммиты, у вас все еще есть «висячие коммиты», потому что на них все еще ссылается reflog на ~ 30 дней. Это сеть безопасности, когда вы удаляете коммиты случайно.

Вы можете использовать команду git reflog для удаления определенных коммитов, перепаковки и т. Д., Или просто команду высокого уровня:

git gc --prune=now
4 голосов
/ 23 января 2017

Вы можете использовать git forget-blob.

Использование довольно просто git forget-blob file-to-forget. Вы можете получить больше информации здесь

https://ownyourbits.com/2017/01/18/completely-remove-a-file-from-a-git-repository-with-git-forget-blob/

Он исчезнет из всех коммитов в вашей истории, reflog, тегов и т. Д.

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

Кредиты для таких авторов, как Сэм Уоткинс

2 голосов
/ 15 декабря 2009

Попробуйте использовать git-filter-branch - он не удаляет большие капли, но он может удалять большие файлы, которые вы указали из всего репо. Для меня это уменьшает размер репо с сотен МБ до 12 МБ.

1 голос
/ 08 сентября 2011

Прежде чем делать git filter-branch и git gc, вы должны просмотреть теги, присутствующие в вашем репо. Любая реальная система, которая имеет автоматические теги для таких вещей, как непрерывная интеграция и развертывания, будет создавать нежелательные объекты, на которые все еще ссылаются эти теги, поэтому gc не может их удалить, и вы все равно будете удивляться, почему размер репо все еще так велик. 1004 *

Лучший способ избавиться от ненужных вещей - запустить git-filter & git gc, а затем подтолкнуть мастера к новому голому репо. У нового голого репо будет зачищенное дерево.

0 голосов
/ 12 февраля 2013

Чтобы добавить еще один совет, не забудьте использовать git remote prune , чтобы удалить устаревшие ветви ваших пультов, прежде чем использовать git gc

вы можете увидеть их с помощью git branch -a

Это часто полезно, когда вы берете из github и разветвленных хранилищ ...

0 голосов
/ 02 декабря 2011

Иногда причина, по которой «gc» не приносит пользы, заключается в том, что есть незаконченная перебазировка или тайник, основанный на старом коммите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...