Как удалить файл из истории Git?

91

Некоторое время назад я добавил информацию (файлы), которая должна быть приватной. Удаление из проекта не проблема, но мне также нужно удалить его из gitистории.

Я использую Git и Github (личный аккаунт).

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

Маркос Р. Гевара
источник
3
Придется переписать историю. К примеру git rebaseтогдаgit push -f
Кори Крамер
4
Возможный дубликат полностью удалить файл из всей истории
коммитов
filter-branchОписано в предлагаемом дубликате метод будет делать то , что вы хотите.
1615903
Также stackoverflow.com/a/17890278, который указывает на BFG, который может быть быстрее, чем использованиеgit filter-branch
Hasturkun
но просто идите быстрее и сделайте то же самое, и вам нужно использовать java. Я читал @Hasturkun
Маркос Р. Гевара

Ответы:

114

Я нашел этот ответ, и это помогло:

git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch path_to_file" HEAD

Нашел здесь https://myopswork.com/how-remove-files-completely-from-git-repository-history-47ed3e0c4c35

Петр Франко
источник
5
Предупреждение: это создает массу коммитов и вызывает расхождения. Тебе, наверное, придется толкать нас силой, но я был слишком напуган.
sudo
1
Поддерживая то, что сказал @sudo, но это сработало для моей новой ветки, которую я случайно выбрал .env. Быстрое и точное решение.
Джо Скотто
1
Действительно, простой силовой толчок работает! Я тоже был напуган, но все поддержал.
wutBruh 04
1
Вы также можете указать диапазон коммитов в качестве последнего аргумента. Если рассматриваемая фиксация была недавней, сделайте это <previous_hash>..HEADи сэкономьте время.
Виктор Сергиенко
после этого работает только у меняgit push --force
Себастьян Шмаль
48

Если вы недавно зафиксировали этот файл или этот файл был изменен за один или два коммита, я предлагаю вам использовать rebaseи cherrypickдля удаления этого конкретного коммита.

В противном случае придется переписывать всю историю.

git filter-branch --tree-filter 'rm -f <path_to_file>' HEAD

Когда вы удовлетворены изменениями и должным образом убедились, что все в порядке, вам необходимо обновить все удаленные ветки -

git push origin --force --all

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

hspandher
источник
после перезаписи всей истории, чтобы сохранить изменения в репозитории (github), что нужно сделать?
Маркос Р. Гевара
спасибо, я подожду, пока это сделаю, и попробую с демо-репозиторием, я обновлю все, что было сделано здесь.
Маркос Р. Гевара
По ошибке забыл добавить --all. Теперь он говорит, что все обновлено, когда я повторно запускаю push с обоими аргументами. И файл не удаляется из других веток. Что мне теперь делать?
Reeshabh Ranjan
Почему в вашем предложении используется, --tree-filterа не --index-filterкак в ответе @PetroFranko?
einpoklum
14
  • удалите файл и перезапишите историю из фиксации, которую вы сделали с удаленным файлом (это создаст новый хеш фиксации из файла, который вы зафиксировали):

    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

  • теперь принудительно нажмите репо:

    git push origin --force --all

  • теперь скажите своим соавторам rebase.

Suhailvs
источник
7

Использование пакета bfg repo-cleaner - еще одна жизнеспособная альтернатива git-filter-branch. Судя по всему, тоже быстрее ...

c1au61o_HH
источник
7
  • Прежде всего, добавьте его в свой .gitignore файл и не забудьте зафиксировать файл :-)
  • Вы можете использовать этот сайт: http://gtiignore.io, чтобы сгенерировать .gitignoreдля вас и добавить требуемый путь к вашим двоичным файлам / папкам

  • После того, как вы добавили файл, .gitignoreвы можете удалить «старый» двоичный файл с помощью BFG.


How to remove big files from the repository

Можно использовать git filter-branchили BFG. https://rtyley.github.io/bfg-repo-cleaner/

BFG Repo-Cleaner

альтернатива git-filter-branch.

BFG - более простая и быстрая альтернатива git-filter-branch для очистки плохих данных. из истории репозитория Git:

* Удаление сумасшедших больших файлов *
* Удаление паролей, учетных данных и других личных данных

Примеры (с официального сайта)

Во всех этих примерах bfg - это псевдоним для java -jar bfg.jar.

# Delete all files named 'id_rsa' or 'id_dsa' :
bfg --delete-files id_{dsa,rsa}  my-repo.git

введите описание изображения здесь

CodeWizard
источник
6

Я прочитал эту статью на GitHub , которая привела меня к следующей команде (похожей на принятый ответ, но немного более надежной):

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
модные штаны
источник
4

git-репо-фильтр

gitрекомендует использовать git-filter-repo (при git filter-branchвыполнении команды). Существует длинный список того, почему он лучше любых других альтернатив ( https://github.com/newren/git-filter-repo#why-filter-repo-instead-of-other-alternatives ), мой опыт что это очень просто и очень быстро.

Эта команда удаляет файл из всех коммитов во всех ветвях:

git filter-repo --path <path to the file or directory> --invert-paths

Можно указать несколько путей с помощью нескольких --pathпараметров. Вы можете найти подробную документацию здесь: https://www.mankier.com/1/git-filter-repo

Тибор Такач
источник