Барев дзес! На связи Гагик Антонян. Я — Frontend-разработчик и это моя первая статья на Хабре. Сегодня вы узнаете, как полноценно удалять .env
, который по ошибке попал на удалённый Github-репозиторий. Буду рад, если поддержите данный материал лайками и комментариями. А теперь погнали рвать пределы IT-галактики.
Разрабатывая приложения, часто сталкиваюсь с тем, как после очередного коммита, в репозитории вижу один из ключевых файлов, когда я работаю с переменными окружениями, оказалась на странице репозитория Github. Речь идет о файле .env
, чей общедоступность может быть опасным. И для того, чтобы обезопасить хранение конфигурационных переменных и настроек приложения, используется данный текстовый файл.
Я работаю на VS Code, и, если честно, так и не понял, с какой стати .gitignore
"не игнорирует" .env.
Причем спокойно "игнорирует" другие файлы, директории.
Всё же, нужно действовать, исходя из конкретного кейса, но если вы не хотите, чтобы какой-нибудь John Doe воспользовался данными из вашего .env
, то вы перешли по верной ссылке. Вы же не отдаете ключи грабителю с фразой "Грабьте мой дом", верно? Так же и тут. Поэтому предлагаю потихоньку начать.
Шаг 1: Создание проекта
В этом шаге я создам приложение Next.js. С этим проектом буду работать на VS Code. Осуществляю создание Next.js-проекта через пакетный менеджер pnpm.
pnpm dlx create-next-app@latest kill-env
После того, как я задал настройки в терминале, как будет выглядеть проект (в статье это не важно), перейдем к коду. Но перед этим хочу связать проект с удаленным репозиторием Github. Итоговую файловую систему можно увидеть на картинке.
Шаг 2: Подключение локального проекта с Github-репозиторием.
Ничего сверхъестественного, здесь создаю репозиторий для моего проекта и делаю последующее связывание с локальным репозиторием. На этой короткой ноте переходим к 3 шагу.
P.S.: Я не буду здесь прописывать и так ясные команды для связывания, поэтому результат представлен на картинке.
Шаг 3: Разбор кейса и его решение
3.1 В какую проблему можно попасть из-за невнимательности
Предположим, что я, увлекшись разработкой чудо-приложения, забыл к коммиту добавить файл .env
в .gitignore
, находящийся в корневой директории проекта. Из-за этого секретный файл попадает на страницу удалённого репозитория, что не хорошо.
Для приличия моего коммита я практически полностью удалил код разметки в одном из файлов моего проекта. Сюр в том, что коммит уже на удалённом репозитории и .env
файл вместе с остальными изменениями. Как не должно быть в вашем репозитории показан на картинке:
Да, .gitignore
файл не отменяет уже зафиксированные изменения (поэтому название папки зависимостей проекта закрашен в серый цвет но не несчастный .env
. Это можно увидеть на приложенной картинке. И так, как мы можем это исправить?
3.2 Решение проблемы
Для начала воспользуемся следующей командой:
git rm -r --cached .env
Не бойтесь, мы удаляем файл .env
и все его подпапки из области подготовки Git, но не из самой файловой системы проекта. Внеся изменения, увидим, что .env
больше не числится в списках файлов проекта.
Если вы думаете, что это happy end, то спешу разочаровать: это ещё не конец. Перейдя на историю коммитов можно обнаружить заманчивую вещь: хоть мы удалили файл из корневой директории проекта, данные из файла .env
как были в истории, так и остались. Не верите? Показываю это на картинке:
Пришло время раз и навсегда расправиться с этой проблемой. Вводим следующую команду, которая удаляет все файлы и папки с именем .env
из истории коммитов текущей ветки (HEAD
):
git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch .env" HEAD
В ответ получим предупреждения о том, что это испортило нашу историю, поскольку это пройдет через всю нашу историю и на 100% устранит её существование. Выполняем следующую команду.
git push --force
После этой команды можно увидеть наши коммиты, однако содержимое файла .env
больше не существует в истории коммитах. Показываю на пикче:
С помощью нескольких команд можно добиться такого результата: и .env
удалён из удалённого репозитория, и не отображается его содержимое в истории коммитов. Надеюсь, что эта статья поможет вам более эффективно отправить на вечный покой файл .env
.
По этой ссылке можно перейти на Notion-статью в укороченной версией с картинками и кодом
Спасибо, что вы прочли эту статью! До скорых встреч!
Комментарии (59)
Mausglov
08.06.2024 15:45+14Я работаю на VS Code, и я, to be honest, так и не понял, с какой стати
.gitignore
"не игнорирует".env.
Причем спокойно "игнорирует" другие файлы, директории.А разгадка проста: это не .gitignore игнорирует "другие файлы, директории" сразу "из коробки", а VS Code. В IDE от JetBrains то же самое.
А .gitignore - просто текстовый файл. Он плюс .git/info/exclude плюс глобальный .gitignore - вот как определяется, будет проигнорирован файл/каталог или нет, если работать не через IDE.
(Надеюсь, ничего не пропустил?)
ajijiadduh
08.06.2024 15:45из статьи понятно что вы не русский, но неужели нельзя было проверить текст с помощью русского человека или каким-нибудь сервисом?
funca
08.06.2024 15:45+3Из вашего комментария тоже понятно, что вы не лингвист. Хотите помочь автору исправить ошибки - есть соответствующая кнопка. Не хотите - не позорьтесь.
ajijiadduh
08.06.2024 15:45как вы это поняли и в чём позор?
radioxoma
08.06.2024 15:45+3В раздельном написании прилагательного https://ru.wiktionary.org/wiki/нерусский в отсутствие противопоставления.
Преисполниться можно здесь.
ednersky
08.06.2024 15:45+1вообще капец: нерусский — прилагательное
неамериканец — существительное
и как в этом мире люди живут?
nukhtarov
08.06.2024 15:45Человек выучил твой язык, а ты ведёшь себя как *, вместо того, чтобы похвалить
kbnrjlvfrfrfrf
08.06.2024 15:45+9Гит ничего не удаляет. Можно пересоздать цепочку чтобы обойти коммит со злосчастным файлом, но сам этот коммит с этим файлом остаётся в этом "блокчейне" навсегда. Сможет ли кто до него добраться не зная хеша - другой вопрос. Ещё раньше можно было писать в суппорт гитхаба чтобы они окончательно удалили коммит. Как сейчас не знаю.
petro_64
08.06.2024 15:45+5Смотря какой гит имеется ввиду: в самом гите он не остаётся навсегда, а до первого вызова сборщика мусора, который удалит коммиты, которые не имеют референсов - если говорить про "обычный" гит. Онлайн сервисы работают по-своему, например Github сборщик мусора не вызывает. Но тем не менее, чекаут с таким коммитом сделать будет невозможно.
kbnrjlvfrfrfrf
08.06.2024 15:45+1Это я и имел ввиду. Свой гит - как бы может особо париться и не надо. А всё это [публично-]облачное баловство - хакнут-сольют, мало ли.
insecto
08.06.2024 15:45+33Фиг с ним с gitignore. Зачем вы вообще изначально добавили .env в staging area перед коммитом? Или вы делали git commit -a? Это плохая привычка, надо избавляться. Или вы ничего не знаете про staging area и всё отдаёте на откуп IDE?
Вообще, конечно, правильный ответ это не переписывать историю (дичь!), а ротировать утёкшие ключи. Как их не чисти, а ключи уже фактически утёкшие.Finesse
08.06.2024 15:45+2Понятно, что ошибку проще не совершать, чем исправить. Но это не значит, что инструкция по исправлению ошибки не нужна.
shaggyone
08.06.2024 15:45+3Про мне автор дал не инструкцию по исправлению ошибки, а инструкцию по маскировке ошибки. Единственный способ что-то сделать это посыпав голову пеплом сообщить ответственному человеку, и уже он перегенерит все скопированные секреты.
GospodinKolhoznik
08.06.2024 15:45+1Подход "Старший придёт он разберётся", конечно имеет право на жизнь, но иногда надо брать ответственность и на себя.
А если я в собственном проекте слил .env файл в гит, то кому "ответственному" мне сообщать?
shaggyone
08.06.2024 15:45+4Знаете, я четверть века назад проходил производственную практику на заводе, токарем. Там висели ещё советские плакаты с текстом: "Рабочий, не скрывай брак, покажи мастеру".
В вашем случае вам нужно перегенерить секреты. Потом можете, и описанное в статье сделать.
GospodinKolhoznik
08.06.2024 15:45+1При чем тут сокрытие брака? И что делать если вы сам мастер? Разве нельзя самостоятельно исправить собственную ошибку и сказать команде - ребята, я там ошибся, поэтому все переделал, так-то и так хакнул репозиторий и перегенерил все ключи и пароли, например?
ednersky
08.06.2024 15:45+5если вы сделали git push, НИКАКИЕ манипуляции на вашей стороне, в том числе push —force не помогут очистить историю на стороне удаленной
зная номер коммита этот файл всё равно можно достать
потому правильную аналогию привели — это попытка сокрытия брака
aamonster
08.06.2024 15:45Это не исправление, вот в чём штука. Исправление – считать ключ утекшим (даже если сделать описанное в статье и сразу умудриться прогнать git gc на сервере – нет никаких гарантий, что кто-то не успел сделать pull) и перегенерить.
Если прав на перегенерацию нет – ну, можно использовать, как временное решение, пока это не сделает тот, кто отвечает за ключи (но в этотвремя находитесь под угрозой).Ну и вообще git push --force – такое себе, создаёт на ровном месте геморрой тем, кто успел сделать git push, так что если есть возможность – лучше обойтись без этой игры в прятки.
shaggyone
08.06.2024 15:45Всё же ваш план работы включает перегенерацию ключей. Если включает, то ок. Хотя непонятно, зачем ритуальное действие с удалением
.env файла
из репозитория.
В контексте нашей с вами беседы, у меня впечатление, что изначально перегенерация не предполагалась, то то что вы не пишете про взятие ответственности это декларация, вроде наклеивания шильдиков о том, что производство местное. Так делать не надо.
vitaly_il1
08.06.2024 15:45+1если репо публичное - да.
а если нет - ИМХО, вполне нормально просто удалить.shaggyone
08.06.2024 15:45Есть варианты.
Пока пишем такую статью мы не должны:
1. считать что гит репозиторий живёт где-то на кошернохаляльном гихтабе или у на аналогичном сервисе. Наример вполне возможен вариант, что читатель воспользовался воспользовался статьёй 15 летней свежести с хабра же, (статья называлась "From Git to Deploy", почему то не гуглится, но есть сотни подобных) и хостит какой то гит у себя, возможно просто пушит в папочку доступную поssh
. Возможно репозиторий ещё с тех времён живёт.
2. Или кто-то из коллег читателя делает бэкап репозитория, bare репозитория, просто на всякий случай. Возможно даже читатель сам 100 лет назад такое организовал, и забыл об этом.
3. возможно сервис корпоративный, который сопровождает корпоративный же девопс, возможно это "девопс после курсов" который знает как квалификационные тесты на этих курсах пройти, умеет проходить собеседования, и даже знает чем отличается симлинк от хардлинка. Но реальную задачу с которой не сталкивался на практике не сделает, условно, вроде такого, что сервис черезsystemd
не сможет запустить, даже если ему пример дать и совместно с ним пару раз этот пример разобрать. И репозиторий декларированный как скрытый на деле -- доступен любому достаточно сильно того желающему.
4. или окажется что сервис которым пользуетесь -- на деле решето.
5. моя личная паранойя в том, что мы на слово верим тому же MS, что их админы не мониторят репозитории на предмет ключей доступа и ещё каких нибудь вкусностей.
На мой взгляд, основной вопрос, это "что будет, если данные утекут". Если хакер упрёт рецепты с сайта до даты их запланированной публикации, наверное не страшно. Если данные там более ценные, я бы не рисковал. На деле, время неспокойное, и условный хакер может развлечься и разместить на сайте с рецептами материал, по поводу которого в одном регионе будут вопросы у властей, или в другом у "прогрессивной общественности". В любом случае, редактирование истории -- сомнительная практика, а в случае компрометации ключей -- это заметание мусора под ковёр.
MadeByFather
08.06.2024 15:45Или вы делали git commit -a? Это плохая привычка, надо избавляться.
Чем? Проще все добавить и убрать что-то не нужное, посмотрев все файлы, чем каждый файл кликать, чтобы добавить в коммит, потому что добавляется как правило 90-95% файлов, так что работы в 10 раз меньше, чем идти от обратного.
wl2776
08.06.2024 15:45добавляется как правило 90-95% файлов
От инструмента зависит. Если CMake + in source build, то она много файлов генерирует.
aamonster
08.06.2024 15:45Без разницы, добавляете вы в индекс файлы по одному или убираете, всё равно вы просматриваете их (а вот git commit -a наводит на мысль, что коммиты слишком жирные, раз их не просматривают)
turboslon
Если с репозиторием работают другие люди, переписывать историю может быть плохой идеей. Тогда можно просто поменять пароли/ключи, которые были упомянуты в файле, и добавить сам файл в
.gitignore