Удаление конфиденциальных файлов и их коммитов из истории Git
Я хотел бы поместить проект Git на GitHub, но он содержит определенные файлы с конфиденциальными данными (имена пользователей и пароли, такие как /config/deploy.rb for capistrano).
Я знаю, что могу добавить эти имена файлов в .gitignore, но это не удалит их историю в Git.
Я также не хочу начинать все сначала, удалив /.каталог git.
есть ли способ удалить все следы конкретного файла в вашем Git история?
10 ответов
для всех практических целей первый вещь, о которой вы должны беспокоиться, это ИЗМЕНЕНИЕ ПАРОЛЕЙ! из вашего вопроса неясно, является ли ваш репозиторий git полностью локальным или у вас есть удаленный репозиторий в другом месте; если он удален и не защищен от других, у вас есть проблема. Если кто-то клонировал этот репозиторий до того, как вы это исправите, у них будет копия ваших паролей на своем локальном компьютере, и вы не сможете заставить их чтобы обновить до вашей "фиксированной" версии, когда она ушла из истории. Единственная безопасная вещь, которую вы можете сделать, это изменить свой пароль на что-то еще везде, где вы его использовали.
С этим из пути, вот как это исправить. GitHub ответил именно на этот вопрос как FAQ:
Примечание для пользователей 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 и другие, клонировал этот удаленный репозиторий, теперь вы находитесь в ситуации, когда переписываете историю. Когда другие попытаются снять ваши последние изменения после этого, они получат сообщение о том, что изменения не могут быть применены, потому что это не быстрая перемотка вперед.
чтобы исправить это, им придется либо удалить существующий репозиторий и повторно клонировать его, либо следовать инструкциям в разделе "Восстановление из восходящей РЕБАЗЫ" в git-rebase man-страницы.
в будущем, если вы случайно совершить некоторые изменения с конфиденциальной информацией, но вы заметите до нажатие на удаленный репозиторий, есть несколько более простых исправлений. Если вы последний коммит, чтобы добавить конфиденциальную информацию, вы можете просто удалить конфиденциальную информацию, а затем запустить:
git commit -a --amend
это изменит предыдущую фиксацию с любыми новыми изменениями, которые вы сделали, включая все удаления файлов, выполненные с помощью git rm
. Если изменения находятся дальше в истории, но все еще не перенесены в удаленный репозиторий, вы можете сделать интерактивную ребазу:
git rebase -i origin/master
это открывает редактор с фиксациями, которые вы сделали с момента вашего последнего общего предка с удаленным репозиторием. Измените " pick "на" edit " в любых строках, представляющих фиксацию с конфиденциальной информацией, и сохраните и закройте. Git пройдет через изменения и оставит вас в месте, где вы можете:
$EDITOR file-to-fix
git commit -a --amend
git rebase --continue
для каждого изменения с конфиденциальная информация. В конце концов, вы вернетесь на свою ветку, и вы можете безопасно нажать новые изменения.
изменение паролей-хорошая идея, но для процесса удаления пароля из истории вашего РЕПО я рекомендую BFG Repo-Cleaner, более быстрая и простая альтернатива 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-50x быстрее, чем работает git-filter-branch
и варианты упрощены и портняжничаны вокруг этих 2 общих использовани-случаев:
- удаление Сумасшедшие Большие Файлы
- удаление пароли, Верительные грамоты и другие личные данные
полное раскрытие информации: я автор РЕПО-очистителя BFG.
рекомендую этот скрипт Дэвид Андерхилл, работал как шарм для меня.
Он добавляет эти команды в дополнение к фильтр-ветви 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, данные скомпрометированы, даже если вы заставите оттолкнуть его через секунду потому что:
-
GitHub продолжает болтаться фиксации в течение длительного времени.
сотрудники GitHub имеют право удалять такие болтающиеся коммиты, если вы обратитесь к ним, однако, что вы должны сделать:Как удалить болтающуюся фиксацию из GitHub?
висячие коммиты можно увидеть либо через:
- веб-интерфейс фиксации: https://github.com/cirosantilli/test-dangling/commit/53df36c09f092bbb59f2faa34eba15cd89ef8e83 (машина Wayback)
- API: https://api.github.com/repos/cirosantilli/test-dangling/commits/53df36c09f092bbb59f2faa34eba15cd89ef8e83 (машина Wayback)
один удобный способ получить источник при этом фиксации - использовать zip загрузки метод, который может принять любую ссылку, например:https://github.com/cirosantilli/myrepo/archive/SHA.zip
-
можно получить отсутствующие SHAs либо по:
- список событий API с
type": "PushEvent"
. Е. Г. мое: https://api.github.com/users/cirosantilli/events/public (машина Wayback) - более удобно иногда, глядя на SHAs запросов pull, которые пытались удалить содержание
- список событий API с
-
есть скрапперы, такие как http://ghtorrent.org/ и https://www.githubarchive.org/ регулярно объединяйте данные GitHub и храните их в другом месте.
Я не мог найти, если они царапают фактический фиксации diff, но это технически возможно.
чтобы проверить это, я создал РЕПО: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
Если вы удалить репозиторий однако коммиты исчезают даже из API сразу и дают 404, например https://api.github.com/repos/cirosantilli/test-dangling-delete/commits/8c08448b5fbf0f891696819f3b2b2d653f7a3824 это работает, даже если вы воссоздаете другой репозиторий с тем же именем.
поэтому мой рекомендуемый курс действий:
изменить верительные грамоты
-
если этого недостаточно (например, голые фото):
- удалить репозиторий
- обратитесь в службу поддержки
чтобы быть ясным: принятый ответ правильный. Попробуй сначала. Однако это может быть излишне сложным для некоторых случаев использования, особенно если вы сталкиваетесь с неприятными ошибками, такими как "fatal: bad revision-prune-empty", или действительно не заботитесь об истории вашего РЕПО.
альтернативой было:
- cd в базовую ветвь проекта
- удалить конфиденциальный код / файл
- rm-rf .Git / # удалить всю информацию git из ваш код
- перейдите в github и удалите свой репозиторий
- следуйте этому руководству, чтобы переместить код в новый репозиторий, как обычно - 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
убедитесь, что путь правильный иначе не получится!--1-->
надеюсь, это поможет
использовать фильтр-филиала:
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
. Вы можете получить больше информации здесь
он исчезнет из всех коммитов в вашей истории, 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 rm --cached /config/deploy.rb
echo /config/deploy.rb >> .gitignore
удалить кэш для отслеживаемого файла из git и добавить этот файл в
.gitignore
список