Удалить большой файл из git
моя первоначальная фиксация содержала некоторые файлы журнала. Я добавил *log мой .gitignore и теперь я хочу удалить файлы журнала из моего репозитория.
удалит файл из репозитория, но также удалит его из локальной файловой системы.
Как удалить этот файл из РЕПО без удаление моей локальной копии файла?
для одного файла:
в одном каталоге:
чтобы удалить всю папку из РЕПО (например, файлы Resharper), сделайте следующее:
я зафиксировал некоторые файлы resharper и не хотел, чтобы они сохранялись для других пользователей проекта.
вы также можете удалить файлы из репозитория на основе ваших .гитюдного без удаления их из локальной файловой системы :
или, альтернативно, в Windows Powershell:
чтобы удалить папку / каталог или файл только из репозитория git, а не из локального попробуйте 3 простых шага.
шаги для удаления каталога
шаги, чтобы игнорировать эту папку в следующей совершает
игнорировать эту папку из next коммиты делают один файл в root с именем .gitignore и добавьте в него имя папки. Вы можете поставить столько, сколько вы хотите
.gitignore файл будет выглядеть так
более общее решение:
ECHO mylogfile.log >> .gitignore
удалить все элементы с индекса.
git rm -r -f --cached .
сделать новый commit
git commit -m "Removed mylogfile.log"
Git позволяет игнорировать эти файлы, предполагая, что они не изменились. Этот делается путем запуска . После маркировки файла как такового, git будет полностью игнорировать любые изменения в этот файл, они не будут отображаться, когда запуск git status или git diff, и они никогда не будут зафиксированы.
следовательно, не удаляя его, но игнорируя изменения в нем навсегда. Я думаю, это работает только локально, поэтому сотрудники могут видеть изменения в нем, если они не выполняют ту же команду, что и выше. (Все еще нужно проверить это.)
выше ответы не работает для меня. Я использовал filter-branch для удаления всех зафиксированных файлов
удалите файл из репозитория git с помощью:
удалите папку из репозитория git с помощью:
это удаляет каталог или файл из всех коммитов
вы можете указать фиксацию, используя:
чтобы подтолкнуть все к удаленному, вы можете сделать:
Если вы хотите просто отследить файл и не удалять его из локального и удаленного РЕПО, используйте эту команду:
Удаление файлов с конфиденциальной информацией из Git-репозитория ( изображение большого размера )
Минимизация ущерба
Итак, вы случайно закоммитили файл с конфиденциальной информацией. Назовём этот файл .env . Сразу после того, как это случилось, надо задать себе пару вопросов:
- Отправлен ли коммит в удалённый репозиторий?
- Является ли удалённый репозиторий общедоступным?
▍Коммит пока не отправлен в удалённый репозиторий
Файлы останутся в рабочей копии репозитория, вы сможете внести в проект необходимые изменения.
Если же вы хотите сохранить коммит и вам нужно просто удалить из него определённые файлы, тогда поступите так:
Параметр --amend можно использовать только для работы с самым свежим коммитом. Если вы, после неудачного коммита, добавили ещё несколько, воспользуйтесь такой командой:
▍Коммит отправлен в удалённый репозиторий
Если вы уже отправили коммит в удалённый репозиторий, то, в первую очередь, вам нужно знать о том, чем отличаются публичные и приватные репозитории.
Если ваш репозиторий является приватным, и при этом он не доступен ботам или людям, которым вы не доверяете, вы можете просто внести поправки в последний коммит, воспользовавшись парой вышеприведённых команд.
Если вы отправили в репозиторий, после проблемного коммита, и другие коммиты, это не помешает вам убрать файлы с конфиденциальными данными из истории Git, воспользовавшись командой git filter-branch или инструментом BFG Repo-Cleaner.
Вот пример использования git filter-branch :
Но, делая это, учитывайте два важных аспекта подобных изменений, вносимых в репозиторий:
- Вы меняете историю Git. Если на текущее состояние репозитория полагаются другие люди, если от этого состояния зависят какие-то ветки того же репозитория, его форки, открытые PR, то это нарушит их работу. В подобных случаях относитесь к репозиторию как к общедоступному и постарайтесь не вносить изменения в его историю.
- Вам нужно будет очистить кеш. Вам понадобится обратиться в службу поддержки платформы, на которой хранится ваш репозиторий, и попросить очистить его кеш. Несмотря на то, что вы исправили проблемный коммит или переписали историю репозитория, старый коммит, содержащий конфиденциальные данные, останется в кеше. Для того чтобы к нему обратиться, нужно будет знать его ID, но к нему можно будет получить доступ до тех пор, пока кеш не очистят.
Нужно ли создавать новые секретные ключи в том случае, если их актуальные версии попали в публичный репозиторий?
Если кратко ответить на вопрос, вынесенный в заголовок, то — нужно. Если ваш репозиторий общедоступен, или если вы, по любой причине, полагаете, что он — не место для хранения секретных данных, вам необходимо будет счесть попавшие в него конфиденциальные данные скомпрометированными.
Даже если вы удалили эти данные из репозитория, вы ничего не сможете сделать с ботами и с форками репозитория. Как же поступить?
- Деактивируйте все ключи или пароли. Это надо сделать в первую очередь. После того, как вы деактивируете ключи, конфиденциальные сведения, ушедшие в общий доступ, оказываются бесполезными.
- Настройте файл .gitignore . Сделайте в .gitignore записи о файлах с конфиденциальной информацией для того чтобы Git не отслеживал бы состояние этих файлов.
- Подготовьте коммит, в котором нет файлов с конфиденциальной информацией.
- Отправьте изменения в репозиторий, снабдите коммит пояснениями о возникшей ситуации. Не пытайтесь скрыть ошибку. Все программисты, работающие над проектом, включая вас, по достоинству оценят наличие в репозитории коммита с разъяснениями ситуации и с описанием того, что именно было исправлено с помощью данного коммита.
Рекомендации по хранению конфиденциальных файлов в проектах, в которых для контроля версий применяется Git
Для того чтобы не допустить утечек конфиденциальной информации стоит придерживаться следующих рекомендаций.
▍Храните секретные данные в файле .env (или в другом подобном файле)
Ключи к API и другие подобные сведения стоит хранить в единственном файле .env . При таком подходе, если Git не отслеживает состояние файла .env , вы, добавив в этот файл новый ключ, не отправите его случайно в репозиторий.
Ещё одно преимущество такого подхода заключается в том, что так у вас будет доступ ко всем ключам через глобальную переменную process .
▍Используйте, если это возможно, ключи API
Скомпрометированные ключи API легко деактивировать, такие ключи легко создать заново. Если это возможно — используйте именно их, а не нечто вроде логинов и паролей.
▍Храните ключи API, пользуясь средствами вашего инструмента для сборки проектов
Ключи API обычно нужны при сборке приложений. Инструменты для сборки проектов, вроде Netlify, позволяют держать ключи в защищённых хранилищах. Такие ключи автоматически внедряются в приложение с использованием глобальной переменной process .
Управление переменными окружения
▍Добавьте запись о файле .env в файл .gitignore
Сделайте так, чтобы Git не отслеживал бы файлы, содержащие конфиденциальную информацию.
▍Подготовьте шаблонный файл .env.template
Наличие подобного шаблонного файла помогает тем, кто работает над проектом, добавлять в проект ключи API, избавляя их от необходимости чтения документации.
▍Не меняйте историю Git в удалённых репозиториях
Постарайтесь строго придерживаться этого правила. Если вы следовали вышеприведённым рекомендациям, то историю Git вам менять и не потребуется.
Итоги
Надеюсь, мой материал поможет вам в безопасной работе с конфиденциальными данными.
А вам случалось отправлять в общедоступный репозиторий что-то такое, что туда попадать не должно?
1.В начале забыл добавить в .gitignore папку target/ в которой хранятся скомпилированные *.jar *.class и прочие файлы. 2.позже через несколько коммитов обнаружил что папка .git весит 12+ мегабайт, по размеру предполагаю что это забытый мной jar файл (кода у меня
15 килобайт, все .class файлы
14 килобайт) 3.нашел этот файл руками он весит 12 МБ и лежит в папке
Прошел несколько вопросов на русском и английском stackoverflow + google пробовал следующее:
- git filter-branch --index-filter 'git rm --cached --ignore-unmatch FILENAME' --prune-empty -- --all
- git filter-branch --index-filter 'git rm --cached --ignore-unmatch FILENAME' HEAD
- git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch FILENAME' --prune-empty --tag-name-filter cat -- --all
Вместо FILENAME пробовал подставлять вот это:
- target/gs-rest-service-0.1.0.jar
- gs-rest-service-0.1.0.jar
- target/
- *.jar
В итоге у меня 2 вопроса: -Как выяснить что это весит 12МБ в папке .git и как это удалить?
вот ссылка на мо проект на github, можно скачать как zip-архив или клонировать:
(да я пытаюсь написать Rest-бэкэнд на Spring Boot'e для крестиков-ноликов)
вы можете посмотреть содержимое каталога target (во всех коммитах):
или информацию о конкретном файле target/gs-rest-service-0.1.0.jar :
удалить файл во всех коммитах можно, например, так:
p.s. если репозиторий был склонирован ещё куда-то/кем-то, то там/тому надо будет принудительно переключиться на отправленную вами переписанную историю:
или просто заново склонировать репозиторий в пустой каталог.
после того, как вы перезаписали историю, объект типа blob, содержащий удалённый файл, стал «осиротевшим». чтобы удалить его, надо воспользоваться командой gc (gargabe collection):
как показывает вывод команды $ du -sb .git (выполненной до и после $ git gc ), занимаемый каталогом .git объём изменился на 242997 байт (13254649-13011652). вероятно, именно столько занимал удалённый файл (в сжатом виде).
после того, как вы перезаписали свою локальную историю, удалённый файл (пока) не стал «осиротевшим» — на него есть ссылки из (пока не переписанной) истории подключенного репозитория (который на github-е находится). после того, как вы перепишете историю и на github-е, команда
должна будет удалить объект типа blob, содержащий этот «осиротевший» файл.
дополнение
полную очистку и упаковку всех объектов, чтобы добиться минимального размера каталога .git , можно выполнить примерно так:
ваш репозиторий (т.е., содержимое каталога .git ), после удаления того большого файла, и полной переупаковки, стал занимать у меня 187165 байт.
Я хотел бы поместить проект Git на GitHub, но он содержит определенные файлы с конфиденциальными данными (имена пользователей и пароли, такие как /config/deploy.rb for capistrano).
Я знаю, что могу добавить эти имена файлов в .gitignore, но это не удалит их историю в Git.
Я также не хочу начинать все сначала, удалив /.каталог git.
есть ли способ удалить все следы конкретного файла в вашем Git история?
для всех практических целей первый вещь, о которой вы должны беспокоиться, это ИЗМЕНЕНИЕ ПАРОЛЕЙ! из вашего вопроса неясно, является ли ваш репозиторий git полностью локальным или у вас есть удаленный репозиторий в другом месте; если он удален и не защищен от других, у вас есть проблема. Если кто-то клонировал этот репозиторий до того, как вы это исправите, у них будет копия ваших паролей на своем локальном компьютере, и вы не сможете заставить их чтобы обновить до вашей "фиксированной" версии, когда она ушла из истории. Единственная безопасная вещь, которую вы можете сделать, это изменить свой пароль на что-то еще везде, где вы его использовали.
Примечание для пользователей Windows: используйте двойные кавычки (") вместо синглов в этой команде
в будущем, если вы случайно совершить некоторые изменения с конфиденциальной информацией, но вы заметите до нажатие на удаленный репозиторий, есть несколько более простых исправлений. Если вы последний коммит, чтобы добавить конфиденциальную информацию, вы можете просто удалить конфиденциальную информацию, а затем запустить:
это изменит предыдущую фиксацию с любыми новыми изменениями, которые вы сделали, включая все удаления файлов, выполненные с помощью git rm . Если изменения находятся дальше в истории, но все еще не перенесены в удаленный репозиторий, вы можете сделать интерактивную ребазу:
это открывает редактор с фиксациями, которые вы сделали с момента вашего последнего общего предка с удаленным репозиторием. Измените " pick "на" edit " в любых строках, представляющих фиксацию с конфиденциальной информацией, и сохраните и закройте. Git пройдет через изменения и оставит вас в месте, где вы можете:
для каждого изменения с конфиденциальная информация. В конце концов, вы вернетесь на свою ветку, и вы можете безопасно нажать новые изменения.
изменение паролей-хорошая идея, но для процесса удаления пароля из истории вашего РЕПО я рекомендую BFG Repo-Cleaner, более быстрая и простая альтернатива git-filter-branch явно предназначен для удаления частных данных из репозиториев Git.
создать private.txt файл с перечислением паролей и т. д., которые вы хотите удалить (по одной записи на строку) , а затем выполните следующую команду:
все файлы под пороговым размером (1 МБ по умолчанию) в вашем история РЕПО будет отсканирована, и любая соответствующая строка (это не в вашем последний commit) будет заменен строкой " * * * REMOVED***". Затем вы можете использовать git gc чтобы очистить мертвые данные:
BFG обычно 10-50x быстрее, чем работает git-filter-branch и варианты упрощены и портняжничаны вокруг этих 2 общих использовани-случаев:
- удаление Сумасшедшие Большие Файлы
- удаление пароли, Верительные грамоты и другие личные данные
полное раскрытие информации: я автор РЕПО-очистителя BFG.
рекомендую этот скрипт Дэвид Андерхилл, работал как шарм для меня.
Он добавляет эти команды в дополнение к фильтр-ветви natacado, чтобы очистить беспорядок, который он оставляет позади:
полный сценарий (все заслуги Дэвида Андерхилла)
последние две команды могут работать лучше, если изменить их на следующие:
Если вы уже нажали на GitHub, данные скомпрометированы, даже если вы заставите оттолкнуть его через секунду потому что:
GitHub продолжает болтаться фиксации в течение длительного времени.
сотрудники GitHub имеют право удалять такие болтающиеся коммиты, если вы обратитесь к ним, однако, что вы должны сделать:Как удалить болтающуюся фиксацию из GitHub?
висячие коммиты можно увидеть либо через:
можно получить отсутствующие SHAs либо по:
Я не мог найти, если они царапают фактический фиксации diff, но это технически возможно.
поэтому мой рекомендуемый курс действий:
изменить верительные грамоты
если этого недостаточно (например, голые фото):
- удалить репозиторий
- обратитесь в службу поддержки
чтобы быть ясным: принятый ответ правильный. Попробуй сначала. Однако это может быть излишне сложным для некоторых случаев использования, особенно если вы сталкиваетесь с неприятными ошибками, такими как "fatal: bad revision-prune-empty", или действительно не заботитесь об истории вашего РЕПО.
Это, конечно, удалит все ветви истории фиксации и проблемы как из вашего репозитория github, так и из вашего локального репозитория git. Если это неприемлемо, вам придется использовать альтернативный вариант подход.
назовите это ядерной опцией.
вот мое решение в windows
git filter-branch --tree-filter" rm-f 'filedir/filename' " HEAD
git push -- force
убедитесь, что путь правильный иначе не получится!--1-->
надеюсь, это поможет
использовать фильтр-филиала:
можно использовать git forget-blob .
использование довольно просто git forget-blob file-to-forget . Вы можете получить больше информации здесь
он исчезнет из всех коммитов в вашей истории, reflog, теги и так далее
кредиты вкладчикам из Stack Overflow, которые позволили мне собрать это вместе
мне пришлось сделать это несколько раз на сегодняшний день. Обратите внимание, что это работает только на 1 файл за раз.
получить список всех коммитов, которые изменили файл. Тот, кто внизу будет первым совершать:
git log --pretty=oneline --branches -- pathToFile
чтобы удалить файл из истории, используйте первую фиксацию sha1 и путь к файлу из предыдущей команды и заполните их этой командой:
git filter-branch --index-filter 'git rm --cached --ignore-unmatch <path-to-file>' -- <sha1-where-the-file-was-first-added>..
Итак, это выглядит примерно так:
удалить кэш для отслеживаемого файла из git и добавить этот файл в .gitignore список
иногда я бросил DVD-rip в проект веб-сайта, а затем небрежно git commit -a -m . , и, Зап, РЕПО было раздуто на 2,2 гига. В следующий раз я внес некоторые изменения, удалил видеофайл и зафиксировал все, но сжатый файл все еще находится в репозитории, в истории.
Я знаю, что могу запускать ветви из этих коммитов и перебазировать одну ветвь на другую. Но что я должен сделать, чтобы объединить 2 коммита, чтобы большой файл не отображался в истории и был очищается в процедуре сбора мусора?
использовать BFG Repo-Cleaner, более простая и быстрая альтернатива git-filter-branch специально разработан для удаления нежелательных файлов из истории Git.
внимательно следуйте инструкция по применению, основная часть как раз это:
любые файлы размером более 100 МБ (которые не находятся в вашем последний commit) будет удален из истории вашего репозитория Git. Затем вы можете использовать git gc убрать мертвых данные:
BFG, как правило, по крайней мере 10-50x быстрее, чем работает git-filter-branch , и, как правило, проще в использовании.
полное раскрытие информации: я автор РЕПО-очистителя BFG.
то, что вы хотите сделать, очень разрушительно, если вы опубликовали историю другим разработчикам. См."восстановление из апстрима перебазировать" в git rebase документация для необходимых шагов после восстановления вашей истории.
у вас есть как минимум два варианта: git filter-branch и интерактивный перебазирования, как описано ниже.
используя git filter-branch
у меня была аналогичная проблема с громоздкими двоичными тестовыми данными из импорта Subversion и написал о удаление данных из репозитория Git.
скажите, что ваша история git:
отметим, что git lola - нестандартный, но очень полезный псевдоним. С --name-status switch, мы можем видеть изменения дерева, связанные с каждой фиксацией.
в" неосторожном " фиксации (имя объекта SHA1 которого ce36c98) файл oops.iso DVD-rip добавлен случайно и удален в следующем коммите, cb14efd. Используя технику описано в вышеупомянутом блоге, команда:
- --prune-empty удаляет коммиты, которые становятся пустыми (то есть, не менять дерево) в результате работы фильтра. В типичном случае этот параметр создает более чистую историю.
- -d имена временного каталога, который еще не существует для создания отфильтрованной истории. Если вы работаете на современном Linux распределение, указав дерево /dev/shm приведет к более быстрому исполнению.
- --index-filter это главное событие и работает против индекса на каждом шаге в истории. Вы хотите удалить oops.iso везде, где он найден, но он не присутствует во всех коммит. Команда git rm --cached -f --ignore-unmatch oops.iso удаляет DVD-rip, когда он присутствует, и не терпит неудачу в противном случае.
- --tag-name-filter описывает как переписать имена тегов. Фильтр cat операция идентичности. Ваш репозиторий, как и пример выше, может не иметь тегов, но я включил эту опцию для полной общности.
- -- указывает конец параметров для git filter-branch
- --all после -- является стенографией для всех refs. Ваш репозиторий, как и пример выше, может иметь только один ref (master), но я включил этот параметр для полной общности.
после некоторого вспенивания история теперь:
обратите внимание, что новый "Неосторожный" commit добавляет только other.html и что фиксация "удалить DVD-rip" больше не находится в главной ветви. Ветка с надписью refs/original/refs/heads/master содержит оригинальные совершает в случае, если вы допустили ошибку. Чтобы удалить его, выполните следующие действия в "контрольный список для сокращения репозитория."
для более простой альтернативы клонируйте репозиторий, чтобы отбросить ненужные биты.
С помощью file:///. clone URL копирует объекты, а не создает только жесткие ссылки.
теперь ваша история:
имена объектов SHA1 для первых двух коммитов ("индекс "и" страница администратора") остались прежними, потому что операция фильтра не изменила эти коммиты. "Неосторожный" заблудился!--17--> и "страница входа" получила нового родителя, поэтому их SHA1s сделал изменить.
интерактивные перебазирования
вы действительно хотите удалить oops.iso от "нерадивого" как хотя вы никогда не добавляли его, а затем "удалить DVD-rip" бесполезно для вас. Таким образом, наш план перехода в интерактивную ребазу-сохранить "страницу администратора", отредактировать "небрежно" и отбросить "удалить DVD-rip."
под управлением $ git rebase -i 5af4522 запускает редактор со следующим содержанием.
выполняя наш план, мы изменяем его на
то есть мы удаляем строку с "Remove DVD-rip "и меняем операцию на" Careless " на edit а не pick .
это дает история:
почему бы не использовать эту простую, но мощную команду?
на --tree-filter опция запускает указанную команду после каждой проверки проекта, а затем возобновляет результаты. В этом случае вы удаляете файл с именем DVD-rip из каждого снимка, независимо от того, существует он или нет.
эти команды работали в моем случае:
он немного отличается от приведенных выше версий.
для тех, кому нужно нажать это на github / bitbucket (я только проверил это с bitbucket):
этот сценарий оболочки отображает все объекты blob в репозитории, отсортированные от наименьшего до наибольшего.
для моего образца РЕПО он работал около в 100 раз быстрее чем другие найденные здесь.
В моей надежной системе Athlon II X4 он обрабатывает репозиторий ядра Linux С его 5,622,155 объектов в чуть больше минуты.
Базовый Сценарий
когда вы запустите приведенный выше код, вы получите хороший удобочитаемого вывода такой:
Быстрое Удаление Файлов
Предположим, вы хотите удалить файлы a и b от каждого коммита, доступного из HEAD , вы можете использовать эту команду:
CD в локальную рабочую папку и выполните следующую команду:
замените имя папки файлом или папкой, которые вы хотите удалить из данного git хранилище.
после этого выполните следующие команды для очистки локального репозитория:
Теперь нажать все изменения в удаленный репозиторий:
это очистит удаленный репозиторий.
git filter-branch --tree-filter 'rm -f path/to/file' HEAD работал довольно хорошо для меня, хотя я столкнулся с той же проблемой, что и описано здесь, который я решил, следуя предложение.
Сразу отметим, что эти команды могут быть очень разрушительными. Если больше людей работают над РЕПО, им всем придется вытащить новое дерево. Три средние команды не нужны, если ваша цель-не уменьшить размер. Потому что ветвь фильтра создает резервную копию удаленного файла, и он может оставаться там в течение длительного времени.
Если вы знаете, что ваша фиксация была недавней, а не проходила через все дерево, сделайте следующее: git filter-branch --tree-filter 'rm LARGE_FILE.zip' HEAD
я столкнулся с этим с учетной записью bitbucket, где я случайно сохранил ginormous *.резервное копирование СПД моего сайта.
git filter-branch --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch MY-BIG-DIRECTORY-OR-FILE' --tag-name-filter cat -- --all
Relpace MY-BIG-DIRECTORY с соответствующей папкой, чтобы полностью переписать историю (включая теги).
Вы можете сделать это с помощью :
git filter-branch --tree-filter 'rm -rf path/to/your/file' HEAD
использовать Расширения Git, это инструмент пользовательского интерфейса. Он имеет плагин под названием "Найти большие файлы", который находит файлы lage в репозиториях и позволяет удалять их постоянно.
Не используйте "git filter-branch" перед использованием этого инструмента, так как он не сможет найти файлы, удаленные "filter-branch" (Altough "filter-branch" не удаляет файлы полностью из файлов пакета репозитория).
когда вы столкнетесь с этой проблемой, git rm будет недостаточно, так как git помнит, что файл существовал когда-то в нашей истории, и поэтому сохранит ссылку на него.
чтобы сделать вещи хуже, перебазирование также нелегко, потому что любые ссылки на blob предотвратят сборщик мусора git от очистки пространства. Это включает удаленные ссылки и ссылки reflog.
Я собрал git forget-blob , небольшой скрипт, который пытается удалить все эти ссылки, а затем использует git filter-branch для перезаписи каждой фиксации в ветке.
как только ваш blob будет полностью неферментирован, git gc избавится от нее
использование довольно просто git forget-blob file-to-forget . Вы можете получить больше информации здесь
Я собрал это вместе благодаря ответам из переполнения стека и некоторых записей в блоге. Кредиты им!
(для истории, я буду копипастить сюда)
это не сработало, потому что мне нравится переименовывать и перемещать вещи. Поэтому некоторые большие файлы были в папках, которые были переименованы, и я думаю, что gc не смог удалить ссылку на эти файлы из-за ссылки в tree объекты, указывающие на эти файлы. Мое окончательное решение действительно убить его было кому:
мое РЕПО ( .git ) изменен с 32MB на 388KB, что даже фильтр-ветка не может очистить.
Читайте также: