Перейти к содержанию

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

Git позволяет изменять историю коммитов: объединять коммиты, менять их порядок, редактировать сообщения или удалять коммиты. Это мощный инструмент, но требующий осторожности.

Когда можно переписывать историю?

Безопасно: - В локальных фич-ветках, которые еще не отправлены на сервер. - В личных форках, где никто другой не работает. - Перед созданием Pull Request для очистки истории.

Опасно (нельзя): - В общих ветках (main, develop), куда уже делали пуш другие разработчики. - В ветках, над которыми работают коллеги.

Золотое правило: Никогда не переписывайте историю, если коммиты уже отправлены в общий репозиторий и могли быть использованы другими людьми.

Интерактивный Rebase

Основной инструмент для переписывания истории — git rebase -i.

Запуск интерактивного режима

git rebase -i HEAD~N

Где N — количество последних коммитов для редактирования.

Пример для 4 коммитов:

git rebase -i HEAD~4

Откроется редактор со списком коммитов:

pick a1b2c3d Добавить форму логина
pick e4f5g6h Исправить стили
pick h7i8j9k Добавить тесты
pick l0m1n2o Обновить документацию

Команды для каждого коммита

Замените pick на одну из команд:

Команда Описание
p (pick) Оставить коммит без изменений
r (reword) Изменить сообщение коммита
e (edit) Остановиться для внесения изменений в код
s (squash) Объединить с предыдущим коммитом
f (fixup) Как squash, но отбросить сообщение
d (drop) Удалить коммит полностью
x (exec) Выполнить команду shell

Пример: Объединение коммитов (Squash)

Хотим объединить 4 коммита в один чистый:

pick a1b2c3d Добавить форму логина
squash e4f5g6h Исправить стили
squash h7i8j9k Добавить тесты
squash l0m1n2o Обновить документацию

После сохранения откроется редактор для написания итогового сообщения:

Добавить полную функциональность авторизации

- Реализована форма входа
- Добавлена валидация
- Написаны тесты
- Обновлена документация API

Пример: Изменение порядка коммитов

Просто поменяйте строки местами:

pick a1b2c3d Добавить форму логина
pick h7i8j9k Добавить тесты
pick e4f5g6h Исправить стили
pick l0m1n2o Обновить документацию

Пример: Редактирование коммита (Edit)

Если нужно изменить содержимое коммита (добавить забытый файл):

pick a1b2c3d Добавить форму логина
edit e4f5g6h Исправить стили
pick h7i8j9k Добавить тесты

Git остановится на коммите e4f5g6h:

Stopped at e4f5g6h... Исправить стили
You can amend the commit now, with

  git commit --amend

Once you are satisfied with your changes, run

  git rebase --continue

Внесите изменения:

# Добавить забытый файл
git add забытый-файл.css

# Изменить коммит
git commit --amend --no-edit

# Продолжить rebase
git rebase --continue

Изменение последнего коммита

Если нужно просто исправить сообщение или добавить файл в последний коммит:

# Изменить сообщение
git commit --amend -m "Новое сообщение"

# Добавить файл без изменения сообщения
git add забытый-файл
git commit --amend --no-edit

Удаление чувствительных данных из истории

Если вы случайно закоммитили пароль или ключ:

С помощью git filter-repo (рекомендуется)

# Удалить файл из всей истории
git filter-repo --path path/to/secret.txt --invert-paths

# Удалить строку из всех файлов
git filter-repo --replace-text <файл-с-правилами>

С помощью BFG Repo-Cleaner

Быстрее и проще для больших репозиториев:

# Удалить файлы с определенным именем
bfg --delete-files secret.txt

# Удалить строки с паролями
bfg --replace-text passwords.txt

После очистки нужно сделать force push:

git push --force-with-lease origin main

Важно: После удаления чувствительных данных немедленно смените скомпрометированные пароли и ключи!

Разделение одного коммита на несколько

Если сделали большой коммит и хотите разбить его на логические части:

# Откатиться к коммиту перед нужным
git reset --soft HEAD~1

# Теперь все изменения в индексе
# Сделайте первый коммит
git add часть1
git commit -m "Первая часть"

# Второй коммит
git add часть2
git commit -m "Вторая часть"

# И так далее

Или через интерактивный rebase с командой edit.

Последствия переписывания истории

После переписывания истории хеши всех измененных коммитов меняются. Если ветка уже была на сервере:

  1. Локально история изменилась.
  2. На сервере осталась старая история.
  3. При попытке обычного git push получите ошибку.

Нужен force push:

git push --force-with-lease origin <ветка>

Внимание: Все, кто скачал старую версию ветки, должны будут делать git fetch и git reset --hard origin/<ветка>, чтобы синхронизироваться.

Альтернативы переписыванию истории

Если история уже общая, используйте: - Revert — для отмены ошибочных коммитов. - Новые коммиты — для исправления ошибок.


Назад: Git Hooks → | Далее: Стратегии ветвления →