Удалить конфиденциальные файлы и их фиксации из истории Git

Я хотел бы поместить проект Git в GitHub, но он содержит определенные файлы с конфиденциальными данными (имена пользователей и пароли, например /config/deploy.rb для capistrano).

Я знаю, что я могу добавить эти имена файлов в .gitignore, но это не удалит их историю в Git.

Я также не хочу начинать заново, удаляя каталог /.git.

Есть ли способ удалить все трассировки определенного файла в истории Git?

Ответы

Ответ 1

В практических целях первое, о чем вы должны беспокоиться, это ИЗМЕНЕНИЕ ПАРОЛЕЙ! Из вашего вопроса не ясно, является ли ваш git-репозиторий полностью локальным или у вас еще есть удаленный репозиторий; если он удаленный и не защищен от других, у вас есть проблема. Если кто-то клонировал этот репозиторий до того, как вы это исправите, у него будет копия ваших паролей на их локальном компьютере, и вы не сможете заставить их обновиться до "фиксированной" версии, если она ушла из истории. Единственная надежная вещь, которую вы можете сделать, - это сменить пароль на другой, где бы вы его не использовали.


С этим из пути, вот как это исправить. GitHub ответил именно на этот вопрос в виде часто задаваемых вопросов:

Примечание для пользователей Windows: используйте двойные кавычки (") вместо одинарных в этой команде

git filter-branch --index-filter \
'git update-index --remove PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATA' <introduction-revision-sha1>..HEAD
git push --force --verbose --dry-run
git push --force

Обновление 2019 года:

Это текущий код из FAQ:

  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 --force --verbose --dry-run
  git push --force

Имейте в виду, что как только вы отправили этот код в удаленное хранилище, такое как GitHub, а другие клонировали этот удаленный репозиторий, вы попадаете в ситуацию, когда вы переписываете историю. Когда другие попытаются свернуть ваши последние изменения после этого, они получат сообщение, указывающее, что изменения не могут быть применены, потому что это не перемотка вперед.

Чтобы это исправить, им придется либо удалить свой существующий репозиторий и повторно клонировать его, либо следовать инструкциям в разделе "ВОССТАНОВЛЕНИЕ ОТ РЕБАЗЫ UPSTREAM" на странице руководства git-rebase.

Совет: выполнить git rebase --interactive


В будущем, если вы случайно зафиксируете некоторые изменения с помощью конфиденциальной информации, но заметите перед тем, как отправить его в удаленный репозиторий, есть некоторые более простые исправления. Если вы в последний раз добавляли конфиденциальную информацию, вы можете просто удалить конфиденциальную информацию и запустить:

git commit -a --amend

Это изменит предыдущий коммит с любыми внесенными вами новыми изменениями, включая удаление всего файла, сделанное с помощью git rm. Если изменения еще в истории, но они все еще не отправлены в удаленный репозиторий, вы можете выполнить интерактивное обновление:

git rebase -i origin/master

Это открывает редактор с коммитами, которые вы сделали со времени вашего последнего общего предка с удаленным репозиторием. Измените "выбрать" на "редактировать" в любых строках, представляющих коммит с конфиденциальной информацией, и сохраните и выйдите. Git рассмотрит изменения и оставит вас в месте, где вы можете:

$EDITOR file-to-fix
git commit -a --amend
git rebase --continue

Для каждого изменения с конфиденциальной информацией. В конце концов, вы вернетесь в свою ветку и сможете спокойно вносить новые изменения.

Ответ 2

Изменение паролей - хорошая идея, но для процесса удаления пароля из вашей истории репо я рекомендую BFG Repo-Cleaner, более быструю и упрощенную альтернативу до git-filter-branch, явно предназначенных для удаления личных данных из репозиториев Git.

Создайте файл private.txt, в котором перечислены пароли и т.д., которые вы хотите удалить (одна запись в строке), а затем выполните следующую команду:

$ java -jar bfg.jar  --replace-text private.txt  my-repo.git

Все файлы под пороговым размером (по умолчанию 1 МБ) в вашей истории репо будут отсканированы, и любая соответствующая строка (которая не входит в ваш последний фиксат) будет заменена на строку "*** REMOVED ***". Затем вы можете использовать git gc для очистки мертвых данных:

$ git gc --prune=now --aggressive

BFG обычно на 10-50 раз быстрее, чем запуск git-filter-branch, и параметры упрощаются и адаптируются к этим двум распространенным случаям использования:

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

Полное раскрытие: я являюсь автором BFG Repo-Cleaner.

Ответ 3

Я рекомендую этот сценарий Дэвида Андерхилла, работая как прелесть для меня.

Он добавляет эти команды дополнительно natacado filter-branch, чтобы очистить беспорядок, который он оставляет:

rm -rf .git/refs/original/
git reflog expire --all
git gc --aggressive --prune

Полный сценарий (весь кредит Дэвиду Андерхиллу)

#!/bin/bash
set -o errexit

# Author: David Underhill
# Script to permanently delete files/folders from your git repository.  To use 
# it, cd to your repository root and then run the script with a list of paths
# you want to delete, e.g., git-delete-history path1 path2

if [ $# -eq 0 ]; then
    exit 0
fi

# make sure we're at the root of git repo
if [ ! -d .git ]; then
    echo "Error: must run this script from the root of a git repository"
    exit 1
fi

# remove all paths passed as arguments from the history of the repo
[email protected]
git filter-branch --index-filter \
"git rm -rf --cached --ignore-unmatch $files" HEAD

# remove the temporary history git-filter-branch
# otherwise leaves behind for a long time
rm -rf .git/refs/original/ && \
git reflog expire --all && \
git gc --aggressive --prune

Последние две команды могут работать лучше, если они изменены на следующие:

git reflog expire --expire=now --all && \
git gc --aggressive --prune=now

Ответ 4

Если вы нажали на GitHub, принудительное нажатие недостаточно, удалите репозиторий или обратитесь в службу поддержки

Даже если после этого вы нажмете одну секунду, этого недостаточно, как описано ниже.

Единственные действительные направления действий:

  • Что такое утечка изменяемых учетных данных, как пароль?

    • да: немедленно измените свои пароли и рассмотрите возможность использования большего количества ключей OAuth и API!
    • нет (голые фото):

      • Вас волнует, если все проблемы в хранилище будут уничтожены?

        • нет: удалить репозиторий
        • да:

          • обратитесь в службу поддержки
          • если утечка очень важна для вас, до такой степени, что вы готовы получить некоторое время простоя репозитория, чтобы уменьшить вероятность утечки, сделайте его закрытым, пока вы ждете ответа от поддержки GitHub

Force pushing a second later is not enough because:

Однако если вы удаляете репозиторий, а не просто принудительно нажимаете, коммиты немедленно исчезают даже из API и дают 404, например, https://api.github.com/repos/cirosantilli/test-dangling-delete/commits/8c08448b5fbf0f891696819f3b2b2d653f7a3824 Это работает, даже если вы воссоздаете другой репозиторий с тем же именем.

Чтобы проверить это, я создал репо: https://github.com/cirosantilli/test-dangling и сделал:

git init
git remote add origin [email protected]:cirosantilli/test-dangling.git

touch a
git add .
git commit -m 0
git push

touch b
git add .
git commit -m 1
git push

touch c
git rm b
git add .
git commit --amend --no-edit
git push -f

См. также: Как удалить оборванный коммит из GitHub?

Ответ 5

Чтобы быть ясным: принятый ответ правильный. Сначала попробуйте. Тем не менее, это может быть излишне сложным для некоторых случаев использования, особенно если вы столкнулись с такими неприятными ошибками, как "фатальный: плохой вариант -" пустой "), или действительно не заботятся об истории вашего репо.

Альтернативой может быть:

  • cd для ветвления базы проекта
  • Удалить секретный код/​​файл
  • rm -rf.git/# Удалить все git информацию от ваш код
  • Перейдите в github и удалите репозиторий
  • Следуйте этому руководству, чтобы подтолкнуть ваш код к новому репозиторию, как обычно, https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/

Это, конечно же, удалит все ветки истории фиксации и проблемы как с вашим реестром github, так и с локальным репо git. Если это неприемлемо, вам придется использовать альтернативный подход.

Назовите это ядерным вариантом.

Ответ 6

Вот мое решение в windows

git filter-branch --tree-filter "rm -f 'filedir/filename'" HEAD

git push -force

убедитесь, что путь правильный в противном случае он не будет работать

Я надеюсь, что это поможет

Ответ 7

Используйте ветвь фильтра:

git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch *file_path_relative_to_git_repo*' --prune-empty --tag-name-filter cat -- --all

git push origin *branch_name* -f

Ответ 8

Вы можете использовать git forget-blob.

Использование довольно простое git forget-blob file-to-forget. Вы можете получить больше информации здесь

https://ownyourbits.com/2017/01/18/completely-remove-a-file-from-a-git-repository-with-git-forget-blob/

Он исчезнет из всех коммитов в вашей истории, журналов, тегов и т.д.

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

Кредиты для авторов из Кару, которые позволили мне собрать это воедино

Ответ 9

Итак, он выглядит примерно так:

git rm --cached /config/deploy.rb
echo /config/deploy.rb >> .gitignore

Удалите кеш для отслеживаемого файла из git и добавьте этот файл в список .gitignore

Ответ 10

Мне приходилось делать это несколько раз. Обратите внимание, что это работает только по 1 файлу за раз.

  • Получить список всех коммитов, которые изменили файл. Тот, который находится внизу, будет первым:

    git log --pretty=oneline --branches -- pathToFile

  • Чтобы удалить файл из истории, используйте первый commit sha1 и путь к файлу из предыдущей команды и заполните их в эту команду:

    git filter-branch --index-filter 'git rm --cached --ignore-unmatch <path-to-file>' -- <sha1-where-the-file-was-first-added>..

Ответ 11

В моем проекте Android у меня был admob_keys.xml в виде отдельного XML файла в папке app/src/main/res/values /. Для удаления этого чувствительного файла я использовал приведенный ниже скрипт и работал отлично.

git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch  app/src/main/res/values/admob_keys.xml' \
--prune-empty --tag-name-filter cat -- --all