Контроль истории Git

D2

Администратор
Регистрация
19 Фев 2025
Сообщения
4,380
Реакции
0
Чтобы понять что тут изложено, нужно обладать хотя бы базовыми навыками работы с Git.

Система контроля версий (Git) хранит в хронологическом порядке все изменения выполненные в отслеживаемых git add файлах. Для каждого изменения git commit сохраняет diff с меткой времени, информацию об авторе и подобное. Diff - это разница между тем, каким знает файл Git и тем что лежит на диске. И по этой истории можно перемещаться вверх-вниз, откатывая или применяя изменения вновь.
Первый раз гит ничего не знает о файле, поэтому git checkout, при откате, удалит файл с диска. Но не из истории коммитов.
Удалить историю тоже можно, git reset позволит откатить изменения с уничтожением коммитов и покрывает кейс линейного отката всех изменений.
Последствия git reset необратимы!

Переписываение истории​

git_1.png



Допустим ситуацию. Был зафиксирован secret.py в котором находится какая-то чувствительная информация. И теперь у нас задача убрать эту информацию.

Первый способ - удалить файл. Если это позволительно.
Хелп команды git filter-branch встречает нас описанием применения

Lets you rewrite Git revision history by rewriting the branches mentioned in the <rev-list options>, applying custom filters on each revision.
Нажмите, чтобы раскрыть...

И щедро одаривает примерами.

Suppose you want to remove a file (containing confidential information or copyright violation) from all commits:
Нажмите, чтобы раскрыть...

git filter-branch --tree-filter 'rm secret.py' HEAD

Второй способ - перестроить историю.

git_2.png



Начинать следует от места первого инцедента. В случае на скрине, коммит add secret впервые упоминает чувствительные данные.

git_3.png



Создание новой ветки от этого коммита, приведет к тому, что в новой ветке он станет последним в её истории. Темно-синий фон отделяет коммиты, которые есть в текущей ветке от тех что нет.

git_4.png



Такой контекст позволяет перезаписать чувствительные данные, выполнив amend-коммит.
После такого коммит add secret потерял темно-синий фон, потому что теперь в этом месте история разделяется. И появляется новая линия, которая сигнализирует о расхождении в истории.

Следующий шаг - это перемещение остальных коммитов из мастера в текущую ветку new-age.
Выбираются все коммиты, кроме add secret. Если выбрать этот коммит к ошибке не приведет, а добавит работы, на один merge-конфликт будет больше. И на один коммит будет больше.
Выбранные коммиты, нужно git cherry-pick-нуть и за-git merge-ить конфликты. Так как первая строка secret.py менялась много раз. И при пике коммита, в котором эта строка менялась, будет запрошено действие пользователя для принятия окончательного решения.

git_5.png



Результат cherry-pick.
Светло-синий фон это отмеченные из мастера коммиты для перемещения. Темно-синий - это коммиты в текущей ветке.

git_7.png



Текущий контекст: master - отмечаный на удаление и new-age - с результатом. Лучше сделать бекап мастера, затем удалить и создать ветку от new-age с имененм master.

Редактирование информации о коммитах​

git filter-branch можно попросить поменять что-то в коммитах, например имя пользователя или его email.
На случай если мыло просочиться в коммиты.

Bash: Скопировать в буфер обмена
Код:
git filter-branch --env-filter '
       if test "$GIT_AUTHOR_EMAIL" = "user@localhost"
       then
               GIT_AUTHOR_EMAIL=count0@example.com
       fi
' -- --all

git_7.png



На всех скринах выше выдно, что пользователь user@localhost, эта команда поменяет его на count0@localhost

git_8.png



И вот он результат.
 
Сверху Снизу