Редакция в git

Недавно я начал работу с небольшим Python script для FTP. Для начала я имел данные о сервере, логине и пароле для FTP-сайта, подключенного к устройству script, но это не имело значения, потому что я работал только с ним локально.

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

Вопрос в том, есть ли способ пройти через историю git и удалить имя пользователя и пароль повсюду, но в противном случае оставить историю неповрежденной? Или мне нужно запустить новое репо без истории?

Ответы

Ответ 1

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

Теперь, для вашего вопроса о том, как редактировать историю. Для этой цели предназначена команда git filter-branch; он будет проходить через каждую фиксацию в истории вашего репозитория, применять команду для ее изменения, а затем создавать новую фиксацию.

В частности, вы хотите git filter-branch --tree-filter. Это позволяет редактировать содержимое дерева (фактические файлы и каталоги) для каждой фиксации. Он будет запускать команду в каталоге, содержащем все дерево, ваша команда может редактировать файлы, добавлять новые файлы, удалять файлы, перемещать их и т.д. Git затем создаст новый объект фиксации со всеми теми же метаданными (сообщение фиксации, дата и т.д.) как предыдущее, но с деревом, измененным вашей командой, обработкой новых файлов как добавлением, отсутствием файлов как удаляет и т.д. (поэтому вашей команде не нужно делать git add или git rm, просто нужно изменить дерево).

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

git filter-branch --tree-filter "sed -i -e 's/SekrtPassWrd/REDACTED/' myscript.py" -- --all

Не забудьте сделать это с копией вашего репозитория, поэтому, если что-то пойдет не так, у вас все еще будет оригинал и вы можете начать заново. filter-branch также сохранит ссылки на ваши исходные ветки, как original/refs/heads/master и т.д., поэтому вы сможете восстановить, даже если вы забудете это сделать; при выполнении некоторых глобальных изменений в моей истории исходного кода, мне нравится, чтобы у меня было несколько резервных копий на случай, если что-то пойдет не так.

Чтобы объяснить, как это работает более подробно:

sed -i -e 's/SekrtPassWrd/REDACTED/' myscript.py

Это заменит SekrtPassWrd в вашем файле myscript.py на REDACTED; параметр -i для sed сообщает ему, что он редактирует файл на месте, без файла резервной копии (поскольку эта резервная копия будет подхвачена Git как новый файл).

Если вам нужно сделать что-то более сложное, чем одна подстановка, вы можете написать script и просто вызвать это для своей команды; просто обязательно вызовите его с абсолютным именем пути, так как git filter-branch вызовите свою команду из временного каталога.

git filter-branch --tree-filter <command> -- --all

Это сообщает git запустить фильтр дерева, как описано выше, над каждой ветвью вашего репозитория. Часть -- --all сообщает Git применить это ко всем ветвям; без него он будет редактировать историю текущей ветки, оставляя все остальные ветки неизменными (что, вероятно, не то, что вы хотите).

См. документацию по GitHub на Удаление чувствительных данных (как изначально указано MBO) для получения дополнительной информации о копировании информации, которая была перенесена в GitHub. Обратите внимание, что они повторяют мой совет по изменению пароля и дают несколько советов по работе с кэшированными копиями, которые все еще могут иметь GitHub.

Ответ 2

Может быть, просто проще сменить пароль на FTP-сайте? Если вы не смущены кодом...

Ответ 3

Я считаю, что вы должны иметь возможность изменить все свои фиксации с помощью команды filter-branch. Подробнее см. раздел в книге ProGit.

Однако, как @MBO ссылки примечания

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

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

Ответ 4

Чтобы добавить к выбранный ответ @Brian Campbell, у меня были проблемы с его кодом в моем использование случай. Я просто отсутствовал в файле, о котором идет речь, в более ранних сообщениях. Я уверен, что я не единственный человек в этой ситуации, поэтому я сделал простой файл fix/hack

git filter-branch --tree-filter "sed -i -e 's/SekrtPassWrd/REDACTED/' myscript.py || echo 'fail'" -- --all

Все, что я сделал, это добавить || echo 'fail', чтобы гарантировать, что код будет работать даже тогда, когда файл не был найден в commit. Я надеюсь, что кто-то еще найдет это полезным или может ответить лучшим методом обработки отсутствующих файлов. Мне не хватает репутации, поэтому я должен был дать новый ответ.