Гілки та хірургія

Параметри злиття

Звичайне злиття — це одна кнопка, і здебільшого на цьому історія й закінчується. Ця сторінка — про решту випадків: lockfile, який конфліктує при кожному злитті, файл, якому хтось перевпорядкував відступи, чужий проєкт, підключений усередину вашого, шляхи якого не збігаються. Git має перемикачі для всіх трьох уже багато років; просто вони поховані на сторінці мануалу, яку ніхто не відкриває посеред конфлікту.

Клацніть гілку правою кнопкою → Злити з параметрами… — у рядках гілок і віддалених репозиторіїв на бічній панелі і на кольорових значках рефів у графі, які мають спільний блок меню, — або ⌘K → Злити з параметрами.

Параметри злиття з точною командою git, виписаною знизу

Команда друкується просто в міру того, як ви її збираєте. Вона там, щоб її можна було звірити з мануалом — і щоб наступного разу запустити її з термінала, без цього діалогу.

Коли фрагмент конфліктує

Вибір Прапорець Означає
Зупинитися й запитати мене — Типова поведінка. Ви розв’язуєте конфлікт самі
Залишити бік цієї гілки -X ours Конфліктні фрагменти розв’язуються на користь того, що вже вивантажене
Узяти бік, що входить -X theirs Конфліктні фрагменти розв’язуються на користь гілки, яка приходить

-X ours — це не -s ours. Перемикач тут вирішує долю лише тих фрагментів (hunks), які справді зіткнулися; усі інші зміни з другої гілки зливаються звичайним чином. Стратегія на ім’я ours — якої Gitcito не пропонує — бере ваше дерево цілком і викидає другий бік геть, породжуючи коміт злиття, який запевняє, що містить роботу, якої в ньому немає. Ця різниця — найчастіше неправильно зрозуміла річ у злиттях git.

Він не може вирішити все. Конфлікт «змінено/видалено» — один бік відредагував файл, другий його видалив — це не текстовий фрагмент, і -X лишає його вам. І це правильно: не існує такої версії «надавати перевагу нашому», яка відповідала б на питання, чи має видалений файл повернутися.

Пробіли

Вибір Прапорець
Ігнорувати зміни в наявних пробілах -X ignore-space-change
Ігнорувати пробіли повністю -X ignore-space-at-eol, -X ignore-all-space

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

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

Що записати

Вибір Прапорець Із чим ви лишаєтеся
Перемотувати вперед, коли можливо — Коміт злиття лише тоді, коли історія розійшлася
Завжди робити коміт злиття --no-ff Коміт злиття навіть для перемотування вперед, тож гілка назавжди лишається видимою у графі
Лише перемотування вперед, інакше відмова --ff-only Нічого, якщо знадобилося б справжнє злиття. Корисно як перевірка
Squash --squash Зміни в індексі, злиття не записано, коміт писати вам
Злити, але не комітити --no-commit Злиття в індексі та в процесі, тож ви можете спершу його оглянути чи підправити

Squash і --no-commit — не одне й те саме. Squash узагалі забуває, що злиття відбувалося: git не записує другого предка, і наступного разу гілка виглядатиме незлитою. --no-commit — це злиття в процесі, яке просто чекає на вас: MERGE_HEAD встановлено, і коміт завершує його як звичайно.

--ff-only не падає тихцем. Якщо знадобився б коміт злиття, git відмовляється й ніщо не зрушує з місця — саме це й робить його доброю перевіркою здорового глузду перед скриптованим злиттям.

Стратегія

Стратегія Для чого
Типова (ort) Для всього. Сучасне тристороннє злиття git
subtree Два боки живуть за різними шляхами — проєкт, вкладений у підкаталог цього
resolve Старе тристороннє злиття. Часом дає раду там, де ort здається на історії з перехресними злиттями

-s subtree — та, яку варто запам’ятати. Злиття оновлень із проєкту, що лежить у vendor/parser/, інакше читалося б як «усі файли видалено, усі файли додано»; стратегія subtree спершу вираховує зсув шляхів. Увесь робочий процес описано в піддеревах.

Чому це конфліктує

Усередині розв’язувача конфліктів є кнопка Чому це конфліктує. Вона запускає git log --merge для файла, що перед вами, і перелічує — окремо по кожному боці — коміти, які його торкалися відтоді, як гілки розійшлися.

Коміти з кожного боку, які торкалися конфліктного файла

Маркери конфлікту кажуть, що зіткнулося. Це каже, хто це змінив, коли й навіщо — а саме це зазвичай і є питання, яке насправді вирішує результат, і причина піти й запитати когось, перш ніж обирати бік.

Якщо тут нічого не показано, жоден бік не комітив зміни саме до цього файла: зіткнення походить від перейменування або переміщення каталогу вище.

Межі, про які варто знати

  • Параметри діють на одне злиття. Вони не запам’ятовуються й не змінюють ані звичайний пункт Злити в поточну, ані меню перетягування.
  • Скасування все одно працює: злиття, запущене з параметрами, записує той самий запис скасування, який повертає до ORIG_HEAD.
  • Восьминогі злиття (більш ніж двох гілок одночасно) тут не пропонуються.
  • Пункти «Злити X у Y» для окремих рефів у меню коміта лишаються звичайними злиттями. Коли вам потрібні параметри, скористайтеся самим значком рефа.
  • -X вирішує мовчки. Ніщо не позначає, які фрагменти було розв’язано автоматично, тож на важливому злитті прочитайте потім діф, а не довіряйте відсутності конфліктів.

Дивіться також: Злиття та ребейз · Конфлікти · Піддерева · Радар конфліктів

Покращити цей переклад на GitHub