Модуль 06 — Слияние и конфликты

Собрать работу из веток в одну и разобраться, когда изменения пересеклись

Прогресс курса Модуль 6 из 9

Что вы освоите в этом модуле

01

git merge

Слияние всегда выполняется в текущую ветку. Чтобы влить feature/projects в main, сначала переходят на main:

$ git switch main
$ git merge feature/projects

Частая ошибка — выполнить git merge main, находясь в ветке функции. Это тоже слияние, но в обратную сторону: основная ветка вливается в ветку функции. Так делают намеренно, чтобы подтянуть свежие изменения, — но не когда хотят выложить функцию.

02

Перемотка: fast-forward

Если после ответвления в main ничего не коммитили, сливать нечего — достаточно передвинуть указатель main вперёд:

До:      e15d2f0 ◀── a3f9c21 ◀── 5d8e0f3 ◀── 9c2a7e1
                       │                       │
                      main             feature/projects

$ git merge feature/projects
Updating a3f9c21..9c2a7e1
Fast-forward
 projects.html | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

После:   e15d2f0 ◀── a3f9c21 ◀── 5d8e0f3 ◀── 9c2a7e1
                                               │
                                   main, feature/projects

История остаётся прямой линией, нового коммита нет. Минус: из истории не видно, что эти коммиты делались в отдельной ветке.

03

Коммит слияния

Если пока шла работа в ветке, в main появились другие коммиты, истории разошлись. Git находит общего предка, сводит изменения обеих веток и создаёт коммит слияния — коммит с двумя родителями:

$ git merge feature/projects
Merge made by the 'ort' strategy.
 projects.html | 42 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

$ git log --oneline --graph
*   c71b4a0 (HEAD -> main) Merge branch 'feature/projects'
|\
| * 9c2a7e1 (feature/projects) Добавить карточки проектов
| * 5d8e0f3 Добавить раздел с проектами
* | f3a01c9 Исправить телефон в контактах
|/
* a3f9c21 Добавить форму обратной связи

Git откроет редактор с готовым сообщением «Merge branch …» — его можно оставить. Флаг --no-ff заставляет создать коммит слияния даже там, где возможна перемотка. Многие команды так и работают: каждая функция в истории видна как отдельная «петля».

04

Конфликт слияния

Конфликт возникает, когда обе ветки изменили одни и те же строки одного файла по-разному. Git не знает, какой вариант правильный, и оставляет решение вам. Изменения в разных файлах или в разных местах одного файла сливаются автоматически.

$ git merge fix/contact-phone
Auto-merging contacts.html
CONFLICT (content): Merge conflict in contacts.html
Automatic merge failed; fix conflicts and then commit the result.

$ git status
On branch main
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
        both modified:   contacts.html

В файле Git размечает спорный фрагмент маркерами:

<p>Пишите на почту или звоните:</p>
<<<<<<< HEAD
<p>Телефон: +7 (812) 555-01-01</p>
=======
<p>Телефон: +7 (921) 555-02-02, с 10 до 19</p>
>>>>>>> fix/contact-phone

Маркеры

  • <<<<<<< HEAD======= — вариант текущей ветки (куда вливаем).
  • =======>>>>>>> fix/contact-phone — вариант вливаемой ветки.
05

Разрешение конфликта

Разрешить конфликт — значит отредактировать файл так, как он должен выглядеть в итоге, и убрать все маркеры. Итог не обязан совпадать ни с одним из вариантов: здесь правильно взять новый номер и оставить часы работы.

<p>Пишите на почту или звоните:</p>
<p>Телефон: +7 (921) 555-02-02, с 10 до 19</p>
$ git add contacts.html      # отметить конфликт как разрешённый
$ git commit                 # завершить слияние, сообщение уже подготовлено
[main 2e8d9f4] Merge branch 'fix/contact-phone'
VS Code подсвечивает конфликт и предлагает кнопки над ним: Accept Current Change (оставить свой), Accept Incoming Change (взять вливаемый), Accept Both Changes (оба подряд). Кнопки — лишь быстрый старт: результат всё равно надо прочитать и проверить.
Перед git add найдите оставшиеся маркеры: git diff --check покажет их. Забытый <<<<<<< в HTML сломает вёрстку, в коде — сборку.

Если запутались и хотите начать заново — отмените слияние. Рабочий каталог вернётся к состоянию до git merge:

$ git merge --abort
06

После слияния

Влитая ветка больше не нужна: её коммиты уже есть в main. Удалите её, чтобы список веток показывал только текущую работу:

$ git branch --merged          # ветки, уже влитые в текущую
  feature/projects
  fix/contact-phone
* main

$ git branch -d feature/projects fix/contact-phone
Deleted branch feature/projects (was 9c2a7e1).
Deleted branch fix/contact-phone (was 7e4c1d2).

Как конфликтов становится меньше

  • Короткие ветки: день-два, а не месяц.
  • Регулярно вливать main в свою ветку, чтобы разрешать расхождения по одному.
  • Не смешивать в коммите содержательные правки с массовым переформатированием файла.
  • Договориться в команде, кто какие файлы меняет в ближайшие дни.

Ключевые выводы модуля

Запомните главное

  • Слияние идёт в текущую ветку: сначала git switch main, потом git merge ветка
  • Fast-forward — перемотка указателя; коммит слияния — когда истории разошлись
  • Конфликт — одни и те же строки изменены по-разному в двух ветках
  • Разрешение: отредактировать, убрать маркеры, git add, git commit
  • git merge --abort возвращает всё как было до слияния
Практические задания — на учебном портале. Задания, критерии оценивания, сдача работ и оценки преподавателя — в курсе на portal.nevabit.ru. Учётную запись выдаёт преподаватель.
Модуль 05: Ветки Все модули Модуль 07: GitFlic