25. Вирішення конфліктів

Цілі

  • Навчитися вирішувати конфлікти під час злиття.

01 Злиття main до гілки style

Давайте повернемося до гілки style і зіллємо туди всі нещодавні зміни з гілки main.

Виконайте

git switch style
git merge main

Результат

$ git switch style
Switched to branch 'style'
$ git merge main
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.

Здається, у нас є конфлікт. І це не дивно! Давайте подивимося, що скаже про це Git:

Виконайте

git status

Результат

$ git status
On branch style
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:   index.html

no changes added to commit (use "git add" and/or "git commit -a")

Якщо ви відкриєте index.html, то побачите:

Файл: index.html

<!-- Author: Alexander Shvets (alex@githowto.com) -->
<html>
  <head>
<<<<<<< HEAD:index.html
    <link type="text/css" rel="stylesheet" media="all" href="style.css" />
=======
    <title>Hello World Page</title>
>>>>>>> main:hello.html
  </head>
  <body>
    <h1>Hello, World!</h1>
    <p>Let's learn Git together.</p>
  </body>
</html>

Частина між <<<<<<< >>>>>>> і є конфліктом. Секція зверху відповідає гілці style, що є поточною гілкою (або HEAD) репозиторія. Нижня секція відповідає змінам з гілки main. Git не може вирішити, які зміни застосовувати, тому просить вас розв'язати конфлікт вручну. Ви можете залишити зміни з гілки style або з гілки main, чи об'єднати їх у будь-який спосіб на власний розсуд. Ви також можете зробити будь-які інші зміни у файлі.

До речі, ви помітили, що наша друга зміна, тег <p>, не є частиною конфлікту? Це тому, що Git вдалося злити цю зміну автоматично.

02 Скасування злиття

Перш ніж ми почнемо розв'язувати наш конфлікт, дозвольте мені зазначити, що переходити одразу до розв'язання конфлікту не завжди оптимально. Конфлікт може бути спричинений змінами, про які ви не знаєте. Або ж ці зміни є занадто великими, щоб з конфліктом можна було б впоратися одразу. Тому Git дозволяє скасувати злиття і відновити попередній стан репозиторія. Для цього ви можете скористатися командою git merge --abort, як це було запропоновано командою status, яку ми щойно виконали.

Виконайте

git merge --abort
git status

Результат

$ git merge --abort
$ git status
On branch style
nothing to commit, working tree clean

03 Рішення конфлікту

Після невеличкої медитації ми готові вирішити конфлікт. Давайте запустимо злиття ще раз.

Виконайте

git merge main

Щоб вирішити конфлікт, нам потрібно відредагувати файл до стану, що нас влаштовує, а потім закомітити його як зазвичай. У нашому випадку ми об'єднаємо зміни з обох гілок. Отже, редагуємо файл до наступного стану:

Файл: index.html

<!-- Author: Alexander Shvets (alex@githowto.com) -->
<html>
  <head>
    <title>Hello World Page</title>
    <link type="text/css" rel="stylesheet" media="all" href="style.css" />
  </head>
  <body>
    <h1>Hello, World!</h1>
    <p>Let's learn Git together.</p>
  </body>
</html>

04 Зробіть коміт з розв'язаним конфліктом

Виконайте

git add index.html
git commit -m "Resolved merge conflict"
git status
git log --all --graph

Результат

$ git add index.html
$ git commit -m "Resolved merge conflict"
[style 79ac6fa] Resolved merge conflict

Давайте подивимось на поточний стан нашого репозиторію і переконаємось, що все гаразд:

Виконайте

git status
git log --all --graph

Результат

$ git status
On branch style
nothing to commit, working tree clean
$ git log --all --graph
*   79ac6fa 2023-11-28 | Resolved merge conflict (HEAD -> style) [Alexander Shvets]
|\  
| * 85c14e9 2023-11-28 | Added meta title (main) [Alexander Shvets]
* | a33deed 2023-11-28 | Merge branch 'main' into style [Alexander Shvets]
|\| 
| * ee16740 2023-11-28 | Added README [Alexander Shvets]
* | 0ee0113 2023-11-28 | Renamed hello.html; moved style.css [Alexander Shvets]
* | 903eb1d 2023-11-28 | Included stylesheet into hello.html [Alexander Shvets]
* | 555372e 2023-11-28 | Added css stylesheet [Alexander Shvets]
|/  
* 9288a33 2023-11-28 | Added copyright statement with email [Alexander Shvets]
* b7614c1 2023-11-28 | Added HTML header (tag: v1) [Alexander Shvets]
* 46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
* 78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
* 5836970 2023-11-28 | Initial commit [Alexander Shvets]

05 Розширені можливості злиття

Git не надає жодних графічних інструментів для допомоги зі злиттям, але буде із задоволенням працювати з будь-якими сторонніми інструментами, які ви захочете використовувати (обговорення таких інструментів на StackOverflow).

При роботі з кодом в сучасному інтегрованому середовищі розробки (IDE), такому як Visual Studio або IntelliJ IDEA, ви, швидше за все, будете використовувати вбудований інструмент злиття. Наприклад, ось як виглядає розв'язання конфлікту в IntelliJ IDEA:

IntelliJ IDEA merge tool