Як видалити файл з історії Git?


91

Деякий час тому я додав інформацію (файли), яка має бути приватною. Видалення з проекту не є проблемою, але мені також потрібно видалити його з gitісторії.

Я використовую Git та Github (приватний рахунок).

Примітка: У цій темі щось подібне є show, але ось старий файл, який був доданий до гілки функції, ця гілка об'єдналася з гілкою розробки і, нарешті, об'єдналася для master, оскільки це було зроблено багато змін. Отже, це не те саме, і потрібно змінити історію та приховати ці файли для конфіденційності.


3
Вам довелося б переписати історію. Наприклад, git rebaseтодіgit push -f
Кори Крамер


filter-branchОписано в пропонованому дублікаті метод буде робити те , що ви хочете.
1615903

Також stackoverflow.com/a/17890278, який вказує на BFG, який може бути швидшим, ніж використанняgit filter-branch
Гастуркун,

але просто йдіть швидше і робіть те саме, і потрібно використовувати java, яку я прочитав @Hasturkun
Marcos

Відповіді:


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

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

Примітка: - Це складна операція, і ви повинні бути в курсі того, що робите. Спочатку спробуйте зробити це в демо-сховищі, щоб побачити, як це працює. Вам також потрібно повідомити про це інших розробників, щоб вони тим часом не вносили жодних змін.


після переписування всієї історії, щоб зберегти зміни до сховища (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.



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

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


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-repo-фільтр

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.