Как убрать из Git-репозитория файлы с конфиденциальной информацией
Файлы проиндексированы, написано сообщение коммита, данные отправлены на сервер… И вдруг хочется повернуть время вспять. В коммит попал файл, которого там быть не должно. Когда такое случается, приходит время обращаться к поисковику.

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

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


Удаление файлов с конфиденциальной информацией из Git-репозитория (изображение большого размера)

Минимизация ущерба


Итак, вы случайно закоммитили файл с конфиденциальной информацией. Назовём этот файл .env. Сразу после того, как это случилось, надо задать себе пару вопросов:


▍Коммит пока не отправлен в удалённый репозиторий


Если вы пока не отправили коммит в репозиторий, то, в общем-то, возникшая ситуация никакой угрозы не несёт. Для того чтобы всё исправить, достаточно просто вернуться к предыдущему коммиту:

git reset HEAD^ --soft

Файлы останутся в рабочей копии репозитория, вы сможете внести в проект необходимые изменения.

Если же вы хотите сохранить коммит и вам нужно просто удалить из него определённые файлы, тогда поступите так:

git rm .env --cached
git commit --amend

Параметр --amend можно использовать только для работы с самым свежим коммитом. Если вы, после неудачного коммита, добавили ещё несколько, воспользуйтесь такой командой:

git rebase -i HEAD~{на сколько коммитов нужно вернуться?}

Это позволит исправить неправильный коммит и поможет не потерять изменения, внесённые в проект остальными коммитами.

▍Коммит отправлен в удалённый репозиторий


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

Если ваш репозиторий является приватным, и при этом он не доступен ботам или людям, которым вы не доверяете, вы можете просто внести поправки в последний коммит, воспользовавшись парой вышеприведённых команд.

Если вы отправили в репозиторий, после проблемного коммита, и другие коммиты, это не помешает вам убрать файлы с конфиденциальными данными из истории Git, воспользовавшись командой git filter-branch или инструментом BFG Repo-Cleaner.

Вот пример использования git filter-branch:

git filter-branch --force --index-filter "git rm --cached --ignore-unmatch .env" --prune-empty --tag-name-filter cat -- --all

Но, делая это, учитывайте два важных аспекта подобных изменений, вносимых в репозиторий:


Нужно ли создавать новые секретные ключи в том случае, если их актуальные версии попали в публичный репозиторий?


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

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


Рекомендации по хранению конфиденциальных файлов в проектах, в которых для контроля версий применяется Git


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

▍Храните секретные данные в файле .env (или в другом подобном файле)


Ключи к API и другие подобные сведения стоит хранить в единственном файле .env. При таком подходе, если Git не отслеживает состояние файла .env, вы, добавив в этот файл новый ключ, не отправите его случайно в репозиторий.

Ещё одно преимущество такого подхода заключается в том, что так у вас будет доступ ко всем ключам через глобальную переменную process.

▍Используйте, если это возможно, ключи API


Скомпрометированные ключи API легко деактивировать, такие ключи легко создать заново. Если это возможно — используйте именно их, а не нечто вроде логинов и паролей.

▍Храните ключи API, пользуясь средствами вашего инструмента для сборки проектов


Ключи API обычно нужны при сборке приложений. Инструменты для сборки проектов, вроде Netlify, позволяют держать ключи в защищённых хранилищах. Такие ключи автоматически внедряются в приложение с использованием глобальной переменной process.


Управление переменными окружения

▍Добавьте запись о файле .env в файл .gitignore


Сделайте так, чтобы Git не отслеживал бы файлы, содержащие конфиденциальную информацию.

▍Подготовьте шаблонный файл .env.template


Наличие подобного шаблонного файла помогает тем, кто работает над проектом, добавлять в проект ключи API, избавляя их от необходимости чтения документации.

▍Не меняйте историю Git в удалённых репозиториях


Постарайтесь строго придерживаться этого правила. Если вы следовали вышеприведённым рекомендациям, то историю Git вам менять и не потребуется.

Итоги


Надеюсь, мой материал поможет вам в безопасной работе с конфиденциальными данными.

А вам случалось отправлять в общедоступный репозиторий что-то такое, что туда попадать не должно?