Close

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

Команда git commit --amend и другие способы переписать историю


Введение


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

Основная задача Git — гарантировать, что вы не потеряете внесенные изменений. Но эта система также предназначена для предоставления вам полного контроля над процессом разработки. В числе прочего вы сами определяете то, как выглядит история вашего проекта. Такая свобода создает и вероятность потери коммитов. Git предоставляет команды для перезаписи истории, но предупреждает, что использование таких команд может привести к потере данных.

В Git существует несколько механизмов хранения истории и сохранения изменений. Вот эти механизмы: commit --amend, git rebase и git reflog. Это мощные инструменты для настройки рабочего процесса. По окончании этого обучающего материала вы будете знать команды, которые позволят реструктурировать коммиты Git, и сможете избегать проблем, с которыми приходится сталкиваться при перезаписи истории.

Логотип Git
Связанные материалы

Шпаргалка по Git

Логотип Bitbucket
СМ. РЕШЕНИЕ

Изучите Git с помощью Bitbucket Cloud

Изменение последнего коммита: git commit --amend


Команда git commit --amend — это удобный способ изменить последний коммит. Она позволяет объединить проиндексированные изменения с предыдущим коммитом без создания нового коммита. Ее можно использовать для редактирования комментария к предыдущему коммиту без изменения состояния кода в нем. Но такое изменение не только редактирует последний коммит, но и полностью его заменяет. То есть измененный коммит станет новой сущностью с отдельной ссылкой. Для Git он будет выглядеть как новый коммит, который отмечен звездочкой (*) на схеме внизу. Существует несколько распространенных сценариев использования команды git commit --amend. В следующих разделах мы расскажем о примерах ее использования.

Git commit amend

Изменение комментария к последнему коммиту Git

git commit --amend

Допустим, при выполнении коммита вы допустили ошибку в комментарии к нему. Выполнение этой команды в отсутствие проиндексированных файлов позволяет отредактировать комментарий к предыдущему коммиту без изменения состояния кода.

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

git commit --amend -m "an updated commit message"

Добавление аргумента -m позволяет передать новый комментарий из командной строки, не открывая текстовый редактор.

Изменение файлов после коммита

В следующем примере показан распространенный сценарий разработки с использованием Git. Допустим, вы отредактировали несколько файлов и хотите сделать коммит за одну операцию. Но потом выясняется, что вы забыли добавить один из файлов в самом начале. Для того чтобы исправить эту ошибку, достаточно проиндексировать другой файл и выполнить коммит с флагом --amend:

# Edit hello.py and main.py
git add hello.py
git commit 
# Realize you forgot to add the changes from main.py 
git add main.py 
git commit --amend --no-edit

Флаг --no-edit позволит внести изменения в коммит без изменения комментария к нему. Итоговый коммит заменит неполный коммит. При этом все будет выглядеть так, словно изменения в файлах hello.py и main.py были сделаны за один коммит.

Не используйте amend для публичных коммитов

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

Обзор

Если коротко, команда git commit --amend позволяет добавить новые проиндексированные изменения в последний коммит. С помощью коммита --amend можно добавлять изменения в индекс Git или удалять таковые из него. Если никаких изменений не проиндексировано, при использовании флага --amend вам все равно будет предложено изменить комментарий к последнему коммиту. Будьте осторожны при использовании флага --amend с коммитами, доступными другим членам команды. Изменение коммита, доступного другому пользователю, может привести к путанице и длительным устранениям конфликтов при слиянии.

Изменение старых или нескольких коммитов


Для изменения старых или нескольких коммитов используйте команду git rebase для объединения нескольких коммитов в новый базовый коммит. В стандартном режиме команда git rebase позволяет в буквальном смысле перезаписать историю: она автоматически применяет коммиты в текущей рабочей ветке к указателю head переданной ветки. Поскольку новые коммиты заменяют старые, команду git rebase запрещено применять к коммитам, которые стали доступны публично. Иначе история проекта исчезнет.

В таких или подобных случаях, когда важно сохранить чистую историю проекта, добавление флага -i к команде git rebase позволяет выполнять интерактивную операцию rebase. Это дает возможность изменять отдельные коммиты в процессе, а не перемещать все коммиты. Подробную информацию об интерактивной операции rebase и дополнительных командах перемещения см. на странице git rebase.

Изменение файлов после коммита

Во время операции rebase команда редактирования (e) остановит процесс на указанном коммите и позволит вам внести дополнительные изменения с помощью команды git commit --amend. Git прервет работу и выведет следующее сообщение:

Stopped at 5d025d1... formatting
You can amend the commit now, with



 git commit --amend



Once you are satisfied with your changes, run



 git rebase --continue

Несколько комментариев

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

Склеивайте коммиты для поддержания чистой истории

Команда склеивания (s) позволяет в полной мере понять смысл rebase. Склеивание позволяет указать коммиты, которые нужно объединить в предыдущие коммиты. Таким образом создается «чистая история». Во время перемещения Git будет исполнять указанную команду rebase для каждого коммита. В случае склеенных коммитов Git откроет выбранный текстовый редактор и предложит объединить комментарии к указанным коммитам. Этот процесс можно показать следующим образом:

Обучающие материалы по Git: пример команды git rebase -i

Обратите внимание, что идентификаторы коммитов, измененных с помощью команды rebase, отличаются от идентификаторов каждого из начальных коммитов. Коммиты с маркером pick получат новый идентификатор, если предыдущие коммиты были переписаны.

Современные решения для хостинга Git (например, Bitbucket) предлагают возможности «автосклеивания» при слиянии. Эти возможности позволяют автоматически выполнять rebase и склеивать коммиты ветки при использовании интерфейса решений для хостинга. Дополнительную информацию см. в разделе «Склеивание коммитов при слиянии ветки Git в Bitbucket».

Обзор

Команда git rebase позволяет изменять историю, а интерактивное выполнение rebase «подчищает» за вами следы. Теперь вы можете совершать и исправлять ошибки, оттачивая свою работу и сохраняя чистую, линейную историю проекта.

Страховка: git reflog


Справочные журналы (reflog) — это механизм, который используется в Git для регистрации обновлений, применяемых к концам веток и другим ссылкам на коммиты. Reflog позволяет вернуться к коммитам, даже если на них нет ссылок из какой-либо ветки или метки. После перезаписи истории reflog содержит информацию о старом состоянии веток и позволяет при необходимости вернуться к этому состоянию. Каждый раз при обновлении конца ветки любым способом (переключение веток, загрузка новых изменений, перезапись истории или просто добавление новых коммитов) в reflog добавляется новая запись. В данном разделе мы рассматриваем команду git reflog и стандартные примеры ее использования.

Использование

git reflog

Отображается reflog локального репозитория.

git reflog --relative-date

Отображается reflog с относительными датами (например, 2 недели назад).

Пример

Чтобы понять команду git reflog, давайте разберем пример.

0a2e358 HEAD@{0}: reset: moving to HEAD~2
0254ea7 HEAD@{1}: checkout: moving from 2.2 to main
c10f740 HEAD@{2}: checkout: moving from main to 2.2

В приведенной выше команде reflog показан переход из главной ветки в ветку 2.2 и обратно. Отсюда можно выполнить жесткий сброс к старому коммиту. Последнее действие указано в верхней строчке с пометкой HEAD@{0}.

Если вы случайно переместитесь назад, reflog будет содержать главный коммит, указывающий на (0254ea7) до случайного удаления вами 2 коммитов.

git reset --hard 0254ea7

При использовании команды git reset можно вернуть главную ветку к более раннему коммиту. Это страховка на случай непреднамеренного изменения истории.

Необходимо отметить, что reflog только предоставляет страховку на тот случай, когда изменения попали в коммит в локальном репозитории, и что в нем отслеживаются только перемещения концов веток репозитория. Кроме того, записи reflog имеют определенный срок хранения. По умолчанию этот срок составляет 90 дней.

Дополнительную информацию см. на странице git reflog.

Резюме


В данной статье мы рассмотрели несколько способов изменения истории Git и отмены изменений в Git. Мы вкратце рассмотрели процесс git rebase. Вот основные заключения.

  • Существует несколько способов переписать историю в Git.
  • Используйте команду git commit --amend для изменения последнего комментария.
  • Используйте команду git commit --amend, чтобы внести изменения в последний коммит.
  • Используйте команду git rebase для объединения коммитов и изменения истории ветки.
  • Команда git rebase -i дает более точный контроль над изменениями истории, чем обычный вариант git rebase.

Узнайте больше об описанных командах на соответствующих страницах:


Поделитесь этой статьей
Следующая тема

Рекомендуемые статьи

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

Люди сотрудничают друг с другом, используя стену со множеством инструментов

Блог Bitbucket

Рисунок: DevOps

Образовательные программы DevOps

Демонстрация функций в демо-зале с участием экспертов Atlassian

Как инструмент Bitbucket Cloud работает с Atlassian Open DevOps

Подпишитесь на информационную рассылку по DevOps

Thank you for signing up