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

StackOverflow https://stackoverflow.com/questions/872565

Вопрос

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

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

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

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

Это было полезно?

Решение

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


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

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

git filter-branch --index-filter \
'git update-index --remove filename' <introduction-revision-sha1>..HEAD
git push --force --verbose --dry-run
git push --force

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

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


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

git commit -a --amend

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

git rebase -i origin/master

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

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

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

Другие советы

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

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

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

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

$ git gc --prune=now --aggressive

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

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

Полное раскрытие:Я автор BFG Repo-Cleaner.

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

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

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's 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
files=$@
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

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

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

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

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

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

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

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

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

Принудительного нажатия секундой позже недостаточно, потому что:

Однако, если вы удалите репозиторий вместо того, чтобы просто принудительно отправить его, коммиты немедленно исчезнут даже из 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 git@github.com: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?

Чтобы внести ясность:Принятый ответ правильный.Попробуйте сначала.Однако в некоторых случаях использования это может оказаться излишне сложным, особенно если вы столкнулись с неприятными ошибками, такими как «фатальная:плохая ревизия --prune-empty», или вас действительно не волнует история вашего репозитория.

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

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

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

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

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

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

git push --force

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

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

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

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

Вы можете использовать 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/

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

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

Благодарность участникам Stack Overflow, которые позволили мне собрать это воедино.

На сегодняшний день мне пришлось сделать это несколько раз.Обратите внимание, что это работает только с одним файлом одновременно.

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

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

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

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

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

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

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

В моем проекте Android у меня было admob_keys.xml как отдельный XML-файл в приложение/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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top