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

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

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

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

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

267
задан Stefan 16 мая '09 в 17:49
источник поделиться

10 ответов

Для всех практических целей первое, что вас беспокоит, - это ИЗМЕНЕНИЕ ВАШИХ ПАРОЛЬ! Неясно, не является ли ваш репозиторий 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" в git -rebase manpage.


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

git commit -a --amend

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

git rebase -i origin/master

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

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

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

349
ответ дан natacado 16 мая '09 в 19:04
источник поделиться

Изменение паролей - хорошая идея, но для процесса удаления пароля из вашей истории репо я рекомендую 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.

64
ответ дан Roberto Tyley 02 февр. '13 в 1:46
источник поделиться

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

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

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

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

#!/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
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
15
ответ дан Jason Goemaat 22 нояб. '11 в 4:05
источник поделиться

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

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

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

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

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

8
ответ дан lostphilosopher 26 янв. '15 в 2:38
источник поделиться

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

Чтобы проверить это, я создал репо: 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 Это работает, даже если вы воссоздаете другой репозиторий с тем же именем.

Итак, мой рекомендуемый курс действий:

  • измените свои учетные данные

  • если этого недостаточно (например, обнаженные фотографии):

    • удалить репозиторий
    • поддержка контактов
7
ответ дан Ciro Santilli 包子露宪 六四事件 法轮功 29 сент. '15 в 12:17
источник поделиться

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

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

git push -force

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

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

5
ответ дан vertigo71 02 дек. '16 в 22:19
источник поделиться

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

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

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

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

4
ответ дан nachoparker 23 янв. '17 в 10:41
источник поделиться

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

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
3
ответ дан Shiv Krishna Jaiswal 17 сент. '17 в 17:33
источник поделиться

Мне приходилось делать это несколько раз. Обратите внимание, что это работает только по 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>..

2
ответ дан b01 21 марта '17 в 21:23
источник поделиться

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

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

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

1
ответ дан przbadu 27 апр. '14 в 11:33
источник поделиться

Другие вопросы по меткам