Удалить большой.pack файл, созданный git
Я проверил загрузку файлов в ветку и слил их, а затем пришлось удалить их, и теперь у меня остался большой.pack-файл, от которого я не знаю, как избавиться.
Я удалил все файлы, используя git rm -rf xxxxxx
и я тоже побежал --cached
вариант также.
Может кто-нибудь сказать мне, как я могу удалить большой файл.pack, который в настоящее время находится в следующем каталоге:
.git/objects/pack/pack-xxxxxxxxxxxxxxxxx.pack
Нужно ли мне просто удалить ветку, которая у меня есть, но я больше ее не использую? Или мне нужно что-то еще запустить?
Я не уверен, насколько это важно, но он показывает замок против файла.
Спасибо
РЕДАКТИРОВАТЬ
Вот некоторые выдержки из моей истории bash_history, которые должны дать представление о том, как мне удалось войти в это состояние (предположим, что на данный момент я работаю над веткой git под названием 'my-branch', и у меня есть папка, содержащая больше папок / файлы):
git add .
git commit -m "Adding my branch changes to master"
git checkout master
git merge my-branch
git rm -rf unwanted_folder/
rm -rf unwanted_folder/ (not sure why I ran this as well but I did)
Я думал, что также запустил следующее, но это не появляется в bash_history с другими:
git rm -rf --cached unwanted_folder/
Я также думал, что я выполнил некоторые команды git (например, git gc
), чтобы попытаться привести в порядок файл пакета, но они также не появляются в файле.bash_history.
8 ответов
Проблема в том, что даже если вы удалили файлы, они все еще присутствуют в предыдущих версиях. В этом вся суть Git, в том, что даже если вы удалите что-то, вы все равно сможете получить его обратно, открыв историю.
То, что вы хотите сделать, называется переписывание истории, и это включает в себя git filter-branch
команда.
У GitHub есть хорошее объяснение проблемы на их сайте. https://help.github.com/articles/remove-sensitive-data
Чтобы ответить на ваш вопрос более прямо, вам нужно выполнить команду unwanted_folename_or_folder
заменил соответственно:
git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch unwanted_folename_or_folder' --prune-empty
Это удалит все ссылки на файлы из активной истории репо.
Затем выполнить цикл GC, чтобы принудительно истечь все ссылки на файл и удалить их из файла пакета. Ничто не должно быть заменено в этих командах.
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --aggressive --prune=now
Сценарий A: если ваши большие файлы были добавлены только в ветку, вам не нужно запускать git filter-branch
, Вам просто нужно удалить ветку и запустить сборку мусора:
git branch -D mybranch
git reflog expire --expire-unreachable=all --all
git gc --prune=all
Сценарий B: Тем не менее, на основе вашей истории Bash, похоже, что вы действительно слили изменения в master. Если вы не поделились изменениями с кем-либо (нет git push
еще). Проще всего было бы сбросить мастер обратно до слияния с веткой, в которой были большие файлы. Это исключит все коммиты из вашей ветки и все коммиты, сделанные мастеру после слияния. Таким образом, вы можете потерять изменения - в дополнение к большим файлам - которые вы, возможно, действительно хотели:
git checkout master
git log # Find the commit hash just before the merge
git reset --hard <commit hash>
Затем выполните шаги из сценария А.
Сценарий C: если после слияния произошли другие изменения в ветви или изменения в master, было бы лучше перебазировать master и выборочно включить коммиты, которые вы хотите:
git checkout master
git log # Find the commit hash just before the merge
git rebase -i <commit hash>
В вашем редакторе удалите строки, которые соответствуют коммитам, которые добавили большие файлы, но оставьте все остальное как есть. Сохранить и выйти. Ваша основная ветка должна содержать только то, что вы хотите, а не большие файлы. Обратите внимание, что git rebase
без -p
исключит коммиты слияния, так что вы останетесь с линейной историей для мастера после <commit hash>
, Это, вероятно, хорошо для вас, но если нет, вы можете попробовать -p
, но git help rebase
говорит combining -p with the -i option explicitly is generally not a good idea unless you know what you are doing
,
Затем выполните команды из сценария А.
Выполните следующую команду, заменив PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA
с путем к файлу, который вы хотите удалить, а не только с его именем. Эти аргументы будут:
- Заставить Git обрабатывать, но не проверять, всю историю каждой ветки и тега
- Удалите указанный файл, а также любые пустые коммиты, созданные в результате
- Перезаписать существующие теги
git filter-branch --force --index-filter "git rm --cached --ignore-unmatch PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA" --prune-empty --tag-name-filter cat -- --all
Это принудительно удалит все ссылки на файлы из активной истории репо.
Следующий шаг, чтобы выполнить цикл GC, чтобы все ссылки на файл истекли и были удалены из файла пакета. В этих командах ничего заменять не нужно.
git update-ref -d refs/original/refs/remotes/origin/master
git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git gc --aggressive --prune=now
Как loganfsmyth уже заявил в своем ответе, вам нужно очистить историю git, потому что файлы там продолжают существовать даже после удаления их из репозитория. Официальные документы GitHub рекомендуют BFG, который мне легче использовать, чем filter-branch
:
Удаление файлов из истории
Загрузите BFG с их сайта. Убедитесь, что у вас установлена Java, затем создайте зеркальный клон и удалите историю. Не забудьте заменить YOUR_FILE_NAME
с именем файла, который вы хотите удалить:
git clone --mirror git://example.com/some-big-repo.git
java -jar bfg.jar --delete-files YOUR_FILE_NAME some-big-repo.git
cd some-big-repo.git
git reflog expire --expire=now --all && git gc --prune=now --aggressive
git push
Удалить папку
То же, что и выше, но используйте --delete-folders
java -jar bfg.jar --delete-folders YOUR_FOLDER_NAME some-big-repo.git
Другие опции
BFG также позволяет использовать даже более изящные варианты (см. Документы):
Удалить все файлы размером более 100M из истории:
java -jar bfg.jar --strip-blobs-bigger-than 100M some-big-repo.git
Важный!
При запуске BFG, будьте осторожны, чтобы оба YOUR_FILE_NAME
а также YOUR_FOLDER_NAME
это действительно просто имена файлов / папок. Они не пути, так что-то вроде foo/bar.jpg
не будет работать! Вместо этого все файлы / папки с указанным именем будут удалены из истории репо, независимо от того, по какому пути или ветке они существовали.
Один вариант:
бежать git gc
вручную, чтобы сжать несколько файлов пакета в один или несколько файлов пакета. Эта операция является постоянной (то есть файл большого пакета сохранит свое поведение сжатия), поэтому может быть полезно периодически сжимать репозиторий git gc --aggressive
Другой вариант - сохранить код и.git где-нибудь, а затем удалить.git и начать заново, используя этот существующий код, создав новый репозиторий git (git init
).
Я немного опаздываю на шоу, но в случае, если ответ выше не решил вопрос, я нашел другой способ. Просто удалите определенный большой файл из.pack. У меня была эта проблема, когда я случайно зарегистрировал большой файл 2 ГБ. Я следовал инструкциям, описанным в этой ссылке: http://www.ducea.com/2012/02/07/howto-completely-remove-a-file-from-git-history/
Это использует BFG в соответствии с рекомендациями GitHub, так же, как ответ @Timo, но с небольшим изменением, так как я потратил некоторое время на просмотр параметров CLI.
Допустим, я отправил изображения с более чем60MB
некоторое время назад, и я не могу отменить фиксацию. Я бы просто запустил следующее
java -jar /jarfiles/bfg-1.14.0.jar --delete-files '*.{png,jpg,JPG,PNG}'
Затем я получу предложение запустить следующую команду, которую я сделаю
git reflog expire --expire=now --all && git gc --prune=now --aggressive
Наконец, синхронизируйте изменения на пульте с
git push --force
Вы можете убедиться, что размер файла пакета уменьшился с помощью
du -sh ./
Это более удобное решение, чем кодирующее. почтовый файл. Откройте zip в формате просмотра файлов (отличается от распаковки). Удалите файл.pack. Разархивируйте и замените папку. Работает как шарм!