Что такое коммит в Git
Это способ сохранения обновлений в проекте. Например, разработчик исправил или дополнил код в нескольких местах. Чтобы зафиксировать корректировки, он использует команду git commit и добавляет commit message — короткое сообщение с пояснениями о том, что поменялось. Система делает снимок текущего состояния: сохраняет в текущую ветку репозитория последний файловый набор с информацией о внесенных дополнениях.
Такие снимки нужны для управления обновлениями, отслеживания истории, более структурированного взаимодействия с другими программистами при совместной разработке проектов. Чтобы быстро разобраться в дополнениях кода, понять, какие правки внесены, кто, когда и с какой целью их сделал, достаточно посмотреть commit.
Также команда git commit создает точку, к которой можно вернуться в будущем. Это используется для отката к предыдущей версии кода. Если что-то пойдет не так, можно возвратиться к предыдущему снимку состояния и начать все заново с того места, где все еще работало правильно.
Зачем склеивать коммиты
Создание снимков текущего состояния разбивает процесс разработки программного продукта на отдельные шаги. Если в проекте слишком много таких снимков, история становится громоздкой и запутанной. Поэтому связанные изменения удобнее соединять в логические блоки.
Причины для объединения коммитов:
- структурирование истории проекта,
- оптимизация проведения код-ревью,
- снижение вероятности конфликтов за счет объединения веток,
- внесение нескольких правок багов или незначительных обновлений, которые нет смысла сохранять по отдельности (замена фона, шрифта, исправление ошибки в тексте системного уведомления).
Например, команда разрабатывает многофункциональное приложение. Один из программистов отвечает за создание функции А. Сначала он реализует базовую структуру, затем добавляет функциональность, потом исправляет мелкие баги. Эти три участка работы можно зафиксировать тремя коммитами, например:
- «Создал основу функции А»;
- «Добавил функциональность»;
- «Исправил ошибки в функции А».
Но коллегам достаточно знать о факте готовности функции, поэтому программист консолидирует все три этапа разработки в один, например, «Реализовал функцию А». Это обеспечивает логическую целостность и облегчает работу с кодом другим участникам проекта.
Как объединить коммиты
Сначала убедимся, что у нас нет незафиксированных обновлений кода. Это можно сделать с помощью следующей операции:
git status
Система покажет текущее состояние, включая файлы, которые были изменены, но еще не закоммичены.
Затем проверим, сколько коммитов нужно склеить. Для этого выполним:
git cherry -v project
Система найдет различия между двумя наборами коммитов: сравнит текущий набор с теми, что находятся в ветке project, и покажет все, что отсутствует в project. За вывод сообщений, которые разработчики добавляли при создании commit, отвечает опция -v.
Пример вывода:
+ 1efr2foib34do5gr3e67 Добавлен push
+ 5bhr93t3go354gdjg8o Перекрашен фон push
+ b43abcdt3e7733g33fg Исправлены баги в отображении push
Знак плюс указывает на обновления, которых нет в ветви project. Таким образом, у нас три новых commit. Посмотрим, как их можно склеить.
Команда rebase
При ребейзе запускается интерактивный режим, в котором можно редактировать историю проекта.
Пример:
git rebase -i HEAD~3
После HEAD указывается количество последних commit, которые нужно изменить. В нашем примере это количество равно трем.
На выходе получим файл в текстовом редакторе такого вида:
pick 1efr2foib34do5gr3e67 Добавлен push
pick 5bhr93t3go354gdjg8o Перекрашен фон push
pick b43abcdt3e7733g33fg Исправлены баги в отображении push
Что можно сделать с этими записями:
- pick — оставить как есть содержимое коммита и сообщение commit message;
- reword — переименовать: оставить содержимое, но изменить сообщение;
- edit — отредактировать содержимое;
- drop — удалить;
- squash — склеить данный commit с предыдущим;
- fixup — склеить данный commit с предыдущим, отбросив его сообщение.
Для объединения коммитов подходят операции squash и fixup. При squash можно ввести новое сообщение с обобщенным текстом. При fixup останется первое сообщение, а остальные будут удалены.
Склеим три записи из нашего примера в одну с помощью squash:
pick 1efr2foib34do5gr3e67 Добавлен push
squash 5bhr93t3go354gdjg8o Перекрашен фон push
squash b43abcdt3e7733g33fg Исправлены баги в отображении push
После сохранения и выхода из редактора система предложит ввести новое сообщение. После этого останется всего один коммит, включающий все содержимое трех предыдущих и новое сообщение.Алгоритм ребейза с использованием fixup аналогичен:
pick 1efr2foib34do5gr3e67 Добавлен push
fixup 5bhr93t3go354gdjg8o Перекрашен фон push
fixup b43abcdt3e7733g33fg Исправлены баги в отображении push
Выходим из редактора, и система автоматически соединяет второй и третий commit с первым, оставив только одно сообщение — первое. Все, что сделано в присоединенных коммитах, включено в первый, но их сообщения потеряны.
Результат выполнения fixup — один commit с сообщением «Добавлен push».
Команда merge
Если ребейз переписывает историю, перенося коммиты на новую базу, то merge используется для слияния, то есть объединения двух веток.
Например, чтобы слить обновления из feature в main, выполним следующее:
git checkout main
git merge feature
Система автоматически создаст новый коммит и при этом сохранит всю историю разработки. Однако при большом количестве слияний это усложняет чтение логов. Если обновления затрагивают одни и те же части файла, возникнет конфликт.
Команда reset
Reset отменяет операцию и работает в зависимости от указанного аргумента: --mixed, --soft, --hard.
Чтобы переключиться на последний commit, используется аргумент --soft. Для объединения двух и более последних commit нужно выполнить:
git reset --soft HEAD~n
git commit --amend
Здесь n означает количество commit, которые нужно склеить. Применимо к диапазону, с которым мы работали выше, первая команда выглядит так:
git reset --soft HEAD~2
Эта операция переместит указатель ветки на два обновления назад, но при этом сохранит содержимое всех коммитов. Затем нужно вручную добавить commit message. Флаг --amend откроет текстовый редактор, где можно написать общий комментарий, например, «Исправления и улучшения push».
Как отменить объединение коммитов
Для отмены ребейза используется та же команда reset, но с другим аргументом. Вместо --soft нужно указать --hard в связке с хеш-кодом нужного commit.
Например:
git reset --hard b43abcdt3e7733g33fg
Эта команда откатит репозиторий к состоянию до ребейза.
Чтобы внести правки в последний совершенный коммит, используется --amend. Опция помогает добавить какие-то файлы или комментарий, изменить сообщение, исправить мелкую ошибку. При выполнении --amend старый снимок состояния заменяется новым, то есть commit, который вы исправляете, перезаписывается и больше нигде не фигурирует.