Удалите большой файл .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.
Ответы
Ответ 1
Проблема в том, что даже если вы удалили файлы, они все еще присутствуют в предыдущих версиях. В том-то и дело, что даже если вы удалите что-то, вы все равно сможете вернуть его, открыв историю.
То, что вы хотите сделать, называется переписыванием истории, и в нем задействована команда git filter-branch
.
У GitHub есть хорошее объяснение проблемы на их сайте. https://help.github.com/articles/remove-sensitive-data
Чтобы ответить на ваш вопрос более прямо, вам нужно выполнить следующую команду с соответствующей заменой unwanted_filename_or_folder
:
git filter-branch --index-filter 'git rm -r --cached --ignore-unmatch unwanted_filename_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
Ответ 2
Сценарий A. Если ваши большие файлы были добавлены только в ветку, вам не нужно запускать git filter-branch
. Вам просто нужно удалить ветку и запустить сборку мусора:
git branch -D mybranch
git reflog expire --expire-unreachable=all --all
git gc --prune=all
Сценарий B. Однако похоже, что на основе истории bash вы объединили изменения в мастер. Если вы не поделились изменениями с кем-либо (еще нет git push
). Проще всего было бы reset вернуть мастер до слияния с веткой, в которой были большие файлы. Это устранит все фиксации из вашего ветки и все фиксации, сделанные для освоения после слияния. Таким образом, вы можете потерять изменения - в дополнение к большим файлам - которые вы, возможно, действительно хотели:
git checkout master
git log # Find the commit hash just before the merge
git reset --hard <commit hash>
Затем выполните шаги из сценария A.
Сценарий C. Если бы изменения в ветке или изменились на мастер после слияния, которые вы хотите сохранить, было бы лучше переустановить мастер и выборочно включить фиксации, которые вы хотите:
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
.
Затем запустите команды из сценария A.
Ответ 3
Один вариант:
запустить git gc
вручную, чтобы сконденсировать несколько файлов пакета в один или несколько файлов пакетов.
Эта операция является постоянной (т.е. Файл большого пакета сохранит свое поведение при сжатии), поэтому может быть полезно периодически сжимать репозиторий с помощью git gc --aggressive
Другой вариант - сохранить код и .git где-нибудь, а затем удалить .git и начать снова с использованием этого существующего кода, создав новый репозиторий git (git init
).
Ответ 4
Как уже указывал в своем ответе 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 также позволяет использовать даже более удобные опции (см. Docs) следующим образом:
Удалите все файлы размером более 100M из истории:
java -jar bfg.jar --strip-blobs-bigger-than 100M some-big-repo.git
Важный!
При запуске BFG будьте осторожны, что как YOUR_FILE_NAME
и YOUR_FOLDER_NAME
действительно являются именами файлов и папок. Это не дорожки, поэтому что-то вроде foo/bar.jpg
не будет работать! Вместо этого все файлы/папки с указанным именем будут удалены из истории репо, независимо от того, какой путь или ветвь они существуют.
Ответ 5
Я немного опоздал на шоу, но в случае, если вышеупомянутый ответ не решил запрос, я нашел другой способ. Просто удалите конкретный большой файл из.pack. У меня была эта проблема, когда я случайно зарегистрировался в большом файле размером 2 ГБ. Я выполнил шаги, описанные в этой ссылке: http://www.ducea.com/2012/02/07/howto-completely-remove-a-file-from-git-history/
Ответ 6
Запустите следующую команду, заменив 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
Ответ 7
это более удобное решение, чем кодирующее. почтовый файл. Откройте zip в формате просмотра файлов (отличается от распаковки). Удалить .pack файл. Разархивируйте и замените папку. Работает как шарм!