1. Что такое git merge
Git merge — это операция в системе контроля версий Git, которая объединяет изменения из одной ветки с другой. Когда вы выполняете слияние веток, Git автоматически объединяет изменения, сделанные в одной ветке, с изменениями из другой ветки.
Git merge используется для объединения «целевой» ветки с «исходной» веткой. Git анализирует изменения, сделанные в каждой из этих веток, и пытается автоматически объединить их.
Как объединить main и feature branch
Самым простым вариантом является:
# Переключиться на feature и влить туда main
git checkout feature
git merge main
Или в одну строку:
git merge feature main
git merge создаётся дополнительный коммит слияния (merge commit), который объединяет изменения из двух веток. Этот коммит сохраняет историю обеих веток.
2. Что такое git rebase
Git rebase — это операция в системе контроля версий Git, которая позволяет перебазировать (переместить) коммиты одной ветки на другую ветку.
При выполнении git rebase Git берёт коммиты из вашей текущей ветки и применяет их поверх коммитов другой ветки (чаще всего это ветка, от которой вы решили отойти с помощью ребейза). Это позволяет поддерживать более линейную историю коммитов без лишних слияний.
Перебазирование feature branch в main branch
git checkout feature
git rebase main
Отличия git rebase и git merge
| Критерий | git merge | git rebase |
|---|---|---|
| История коммитов | Создаёт дополнительный коммит слияния; сохраняет историю обеих веток | Переписывает историю; создаются новые коммиты с теми же изменениями поверх целевой ветки |
| Чистота истории | Могут накапливаться «мусорные» коммиты слияния | История становится более чистой и линейной |
| Конфликты | Разрешаются один раз при слиянии | Могут потребоваться при каждом переносимом коммите |
| Безопасность | Более безопасен; не изменяет историю коммитов | Опасен при работе с общедоступными ветками — изменяет историю коммитов |
3. Золотое правило rebase
Мы разобрались, что такое перебазирование. Теперь главное — понять, когда его делать не нужно.
Rebase перемещает все коммиты из основной ветки в feature-ветку. Проблема заключается в том, что это происходит только в вашем репозитории. Все остальные разработчики всё ещё работают с исходной основной веткой. Поскольку перебазирование приводит к созданию совершенно новых коммитов, Git будет считать, что история вашей основной ветки расходится с историей всех остальных.
Единственный способ синхронизировать две основные ветки — это снова слить их вместе, что приведёт к дополнительному коммиту слияния и двум наборам коммитов, содержащих одни и те же изменения.
Что если всё-таки нужно запушить перебазированную ветку?
Если вы попытаетесь отправить перебазированную основную ветку обратно в удалённый репозиторий, Git не позволит вам это сделать. Однако вы можете принудительно выполнить отправку с помощью --force:
git push --force
git push --force перезаписывает историю удалённого репозитория. Другие разработчики не смогут корректно синхронизироваться — их локальные копии «сломаются» и им придётся ручную пересинхронизировать работу.Никогда не использовать
git push --force на main/master в командной работе. Если вам нужно обновить публичную историю, используйте git revert для создания нового коммита, отменяющего изменения.
4. Git commit --amend
Git commit --amend — это команда, которая используется для изменения последнего коммита в репозитории и позволяет внести изменения в последний коммит без создания нового коммита.
Команда очень удобна для исправления небольших ошибок или добавления упущенных изменений в последний коммит.
Как работает
- После выполнения этой команды откроется редактор сообщения коммита, где вы можете внести изменения в сообщение коммита.
- Вы можете добавить новые файлы в индекс перед выполнением
git commit --amend, и они будут включены в исправленный коммит.
# Изменить только сообщение последнего коммита
git commit --amend -m "Новое сообщение коммита"
# Добавить пропущенный файл к последнему коммиту
git add forgotten-file.txt
git commit --amend --no-edit
git commit --amend, изменят историю коммитов в вашем локальном репозитории. Поэтому, если вы уже поделились этим коммитом с другими разработчиками, будьте осторожны — это может создать проблемы с совместной работой.
5. Git reset
Git reset используется для изменения состояния вашего репозитория. Эта команда изменяет указатель HEAD и/или перемещает текущую ветку на определённый коммит.
Основные опции git reset
| Опция | Что происходит | Рабочий каталог | Индекс (staging) |
|---|---|---|---|
--soft |
Сбрасывает HEAD на указанный коммит | Сохраняется | Сохраняется |
--mixed (по умолчанию) |
Сбрасывает HEAD и сбрасывает индекс | Сохраняется | Сбрасывается |
--hard |
Сбрасывает HEAD, индекс и рабочий каталог | УДАЛЯЕТСЯ | Сбрасывается |
# Отменить последний коммит, сохранив изменения в staging
git reset --soft HEAD~1
# Отменить последний коммит, сохранив изменения в рабочем каталоге
git reset --mixed HEAD~1
# Полностью откатить к предыдущему коммиту (ОСТОРОЖНО!)
git reset --hard HEAD~1
git reset --hard HEAD~1 безвозвратно удаляет ВСЕ незакоммиченные изменения в рабочем каталоге и сбрасывает индекс. Восстановить эти данные без резервных копий невозможно.Безопасные альтернативы:
— Используйте
git reset --soft HEAD~1, чтобы сохранить изменения в рабочем каталоге.— На публичных ветках используйте
git revert — он создаёт новый коммит и не меняет историю.— Перед
reset --hard спрячьте изменения через git stash, если хотите их сохранить.
6. Git checkout
Git checkout используется для переключения между ветками и восстановления файлов из репозитория.
Основные использования git checkout
- Переключение между существующими ветками с использованием их имён.
- Создание новых веток на основе существующих веток или коммитов.
- Восстановление файлов из определённого коммита, а не из последней версии ветки.
# Переключиться на ветку main
git checkout main
# Создать и переключиться на новую ветку
git checkout -b feature
# Восстановить файл из репозитория (отменить незакоммиченные изменения)
git checkout -- filename.txt
# Переключиться на определённый коммит (осторожно: Detached HEAD!)
git checkout abc1234
git checkout была разделена на две более специализированные команды:—
git switch feature — для переключения веток (замена git checkout feature)—
git restore filename.txt — для восстановления файлов (замена git checkout -- filename.txt)⚠️ Проверить по документации — доступно начиная с Git 2.23.
7. Git revert
Git revert используется для отмены изменений, внесённых определённым коммитом, путём создания нового коммита, который отменяет изменения этого коммита.
Git revert безопасен для использования в общедоступных ветках, так как он не изменяет историю коммитов, а создаёт новые коммиты, отменяющие изменения.
# Отменить последний коммит (создаст новый коммит-откат)
git revert HEAD
# Отменить конкретный коммит по хэшу
git revert abc1234
# Отменить несколько коммитов (не создавая коммит сразу — --no-commit)
git revert --no-commit HEAD~3..HEAD
Отличия revert от reset
| git revert | git reset |
|---|---|
| Создаёт новый коммит, отменяющий изменения | Изменяет состояние репозитория путём перемещения HEAD |
| Безопасен на общедоступных ветках; история не меняется | Опасен на публичных ветках; изменяет историю коммитов |
| Уведомляет других разработчиков об отмене через новый коммит | Не создаёт новых коммитов; при --hard данные теряются |
git revert. Если на личной локальной ветке — можно использовать git reset, но с осторожностью.