Короткий ответ
git merge создаёт новый merge-коммит, сохраняя историю обеих веток как есть, а git rebase переносит коммиты фиче-ветки поверх новой базовой точки, переписывая их хэши и создавая линейную историю; rebase не стоит применять к веткам, которые уже видели другие разработчики и могут быть у них локально.
Как это работает подробнее
merge находит общего предка двух веток и объединяет изменения одним коммитом с двумя родителями; rebase же пересоздаёт каждый коммит фиче-ветки заново, как будто он был сделан поверх текущего состояния целевой ветки, из-за чего у коммитов меняются хэши.
Пример кода
example-474.sh
git checkout feature/login
git fetch origin
git rebase origin/main # переносит коммиты feature/login поверх актуального main
# альтернатива, если ветка уже публичная и используется другими:
git checkout feature/login
git fetch origin
git merge origin/main # создаёт merge-коммит, история не переписываетсяЧто использовать на практике
- Рекомендация. для личной, ещё не запушенной или запушенной только в свой форк ветки
rebaseдаёт чистую линейную историю перед мерджем в main. Для уже опубликованной общей ветки, над которой работают несколько человек, предпочтительнееmerge, чтобы не переписывать историю, которую кто-то уже вытянул к себе.
Подводные камни
- Ошибка. делать
rebaseнад веткой, которая уже запушена и используется другими — это ломает их локальные копии при следующемpull; путать "переписывание истории" с "потерей данных" — сами изменения не теряются, но меняются идентификаторы коммитов, что ломает ссылки и уже открытые PR с привязкой к хэшам.