← Назад к вопросам

Что такое git merge?

1.3 Junior🔥 111 комментариев
#Git и VCS

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Git Merge: Объединение веток

Git merge — это операция, которая объединяет две ветки в одну. Это основной способ интеграции изменений из одной ветки в другую.

Основная идея

До merge:           После merge:

main                main
  *                   *
  *                   *
  *                   *
  |\                  *
  | *                 |
  | *                 |
  |/                  |
feature             feature
  *                   *

Вы говорите Git: "Возьми все изменения из feature и добавь их в main".

Как это работает

1. Fast-Forward Merge (самый простой случай)

Если в main не было новых коммитов с момента создания feature ветки:

До:                 После:
main -> A           main -> A -> B -> C
        |                       |
        v                       v
feature -> B -> C   feature (указывает туда же)

Git просто переместит указатель main на последний коммит feature. Никакого merge коммита не создается.

git checkout main
git merge feature
# Результат: main указывает на C, feature на C

2. Merge Commit (когда main изменялся)

Если в main были новые коммиты:

До:                     После:
main -> A -> D          main -> A -> D -> M (merge)
        |       ^               |       |
        v       |               v       v
feature -> B -> C       feature -> B -> C

Git создает новый merge коммит M, который объединяет изменения из обеих веток.

git checkout main
git merge feature
# Результат: создается merge коммит с двумя родителями

3. Как Git находит общие предки (3-way merge)

Для безопасного слияния Git использует 3-way merge:

Общий предок (base):   A
                        |
              +---------+--------+
              |         |        |
main версия: A -> D    feature: A -> B -> C

Git сравнивает:

  • Что изменилось в main (A -> D)
  • Что изменилось в feature (A -> C)
  • И если изменения не конфликтуют, объединяет их
# Пример: слияние с изменениями в разных файлах
# Файл main (из D):
users.py:
    def get_user(id):
        return db.query(id)

# Файл feature (из C):
auth.py:
    def login(username, password):
        verify_password(password)

# После merge: оба файла есть в результате
# Конфликта нет, потому что они не пересекаются

Практический пример

Сценарий 1: Простой merge без конфликтов

# Статус: вы на main, feature ветка впереди
git log --oneline --all --graph
* 123abc (feature) Добавил новую фичу
* 456def Написал тесты
* 789ghi (main) Инициальный коммит

# Merge
git merge feature
# Merge made by the 'recursive' strategy.
#  feature.txt | 1 +
#  1 file changed, 1 insertion(+)

# Теперь main указывает на тот же коммит, что и feature
git log --oneline
* 123abc (HEAD -> main, feature) Добавил новую фичу
* 456def Написал тесты
* 789ghi Инициальный коммит

Сценарий 2: Merge с конфликтом

# main имеет новые коммиты
git log --oneline --all --graph
* 111aaa (main) Обновил конфиг
* 789ghi Инициальный коммит
|
* 123abc (feature) Изменил конфиг
* 456def Инициальный коммит

# Оба изменили одну строку в одном файле - КОНФЛИКТ!
git merge feature
# Auto-merging config.py
# CONFLICT (content): Merge conflict in config.py
# Automatic merge failed; fix conflicts and then commit.

# Статус показывает конфликты
git status
# both modified:   config.py

# Открываем config.py и видим
<<<<<<< HEAD
    DEBUG = True  # main версия
=======
    DEBUG = False  # feature версия
>>>>>>> feature

# Решаем вручную (например, берем main версию)
    DEBUG = True

# Помечаем как решено и коммитим
git add config.py
git commit -m "Merge feature into main, resolved config conflict"

Разные типы merge

1. Recursive Merge (default)

Стандартный merge, использует 3-way сравнение.

git merge feature
# Результат: merge коммит (если нужно)

2. Squash Merge

Объединяет все коммиты feature в один коммит и добавляет в main.

git merge --squash feature
# История feature сгруппирована в один коммит

git log --oneline
* abcdef (main) Squashed commit from feature (3 files changed)
* 123xyz Инициальный коммит

Когда использовать: Когда история feature messy и содержит много промежуточных коммитов.

3. Rebase (не совсем merge, но похоже)

Перемещает коммиты feature на top of main.

# Было:          Стало:
# main -> A      main -> A -> B -> C
# feature -> B   feature -> B -> C
#           C

git rebase main
# feature ветка переписана на основе main

Различие: Merge создает merge коммит, rebase переписывает историю.

# Merge: история содержит все коммиты + merge коммит
git log --oneline --graph
*   (merge commit) Merge feature into main
|\
| * (feature коммит)
| * (feature коммит)
* | (main коммит)
|/

# Rebase: линейная история
git log --oneline
* (feature коммит)
* (feature коммит)
* (main коммит)

Workflow: Как merge используется в реальном проекте

GitHub Flow / PR-based workflow

# 1. Создаешь feature ветку
git checkout -b feature/user-auth
git add .
git commit -m "Add user authentication"

# 2. Pushишь в удаленный репозиторий
git push origin feature/user-auth

# 3. Создаешь Pull Request на GitHub
# GitHub создает preview: как будет выглядеть merge
# Коллеги review код

# 4. После одобрения нажимаешь "Merge Pull Request"
# GitHub автоматически делает:
git merge --no-ff feature/user-auth

# 5. Feature ветка удаляется

Gitflow (более сложный workflow)

# develop ветка — основа для разработки
# feature ветки создаются из develop
git checkout -b feature/new-feature develop
# ... работа ...

# Merge обратно в develop
git checkout develop
git merge --no-ff feature/new-feature

# Когда release готов, создаешь release ветку
git checkout -b release/1.0 develop
# ... финальные тесты ...

# Merge в main (production)
git checkout main
git merge --no-ff release/1.0

Важные команды

# Основные
git merge feature              # Merge feature в текущую ветку
git merge --no-ff feature      # Принудительно создать merge коммит
git merge --squash feature     # Сквашить все коммиты в один

# Если что-то пошло не так
git merge --abort              # Отменить merge

# Посмотреть статус merge
git status                      # Показывает конфликты
git diff                        # Показывает различия

# Решение конфликтов
git add <файл>                # Помечаем как решено
git commit                      # Завершаем merge

Fast-Forward vs Merge Commit

Fast-Forward (по умолчанию)

git merge feature
# Просто переместит указатель, если возможно

Плюсы: Чистая линейная история Минусы: Теряется информация о том, что была ветка

Merge Commit (--no-ff)

git merge --no-ff feature
# Всегда создает merge коммит, даже если fast-forward возможен

Плюсы: Видна история веток, информация о слияниях Минусы: История более сложная

Ключевые выводы

  1. Merge объединяет две ветки в одну
  2. Fast-forward — когда main не менялся, merge тривиален
  3. 3-way merge — Git анализирует общего предка для безопасного слияния
  4. Конфликты — когда обе ветки изменяют один код, нужно решить вручную
  5. Merge vs Rebase — merge сохраняет историю веток, rebase делает историю линейной
  6. Pull Request — GitHub/GitLab way для code review перед merge
  7. --squash — когда история feature грязная и нужно объединить в один коммит
Что такое git merge? | PrepBro