Помилка: Git refusing to merge unrelated histories during rebase. Як її виправити?
Фіксимо помилки в роботі з Github
Під час роботи з Github може викинути багато різних помилок. Чи не найпоширеніша з них —
fatal: refusing to merge unrelated histories.
В цій статті розберемось, чому вона масово гуглиться, має десятки відповідей на Stack Overflow та майже завжди з’являється не через «криві руки», а через нерозуміння того, як Git бачить історію проєкту.
Симптом проблеми
Типовий сценарій виглядає абсолютно нормально. Ви хочете підтягнути зміни з віддаленої гілки та зберегти чисту історію, тому виконуєте:
git rebase origin/main
Або:
git pull --rebase
І раптом Git зупиняється з помилкою:
fatal: refusing to merge unrelated histories
На перший погляд, помилка не має сенсу і виглядає дивно. Репозиторій той самий, remote налаштований правильно, гілки мають знайомі назви (main, origin/main), а команда — одна з найбільш стандартних у щоденній роботі.
Але Git поводиться так, ніби ви намагаєтесь об’єднати два повністю різні проєкти, між якими немає нічого спільного. Саме це відчуття «я нічого дивного не роблю, але Git відмовляється» і є головним симптомом проблеми.
Що насправді означає unrelated histories
Коли Git пише unrelated histories, він буквально каже: «я не знайшов жодного спільного “коміту-предка” між цими гілками». Для Git це ключова умова, щоб виконати будь-який merge або rebase.
Важливо розуміти, що Git — це не набір файлів, а граф комітів. Кожен коміт посилається на попередній, утворюючи ланцюжок історії. Коли ви робите merge або rebase, Git шукає точку, де ці дві історії колись розійшлись, і від неї будує подальші дії.
Якщо такої точки немає — Git просто не знає, від чого відштовхуватися.
У спрощеному вигляді це виглядає так:
A───B───C (local main)
X───Y───Z (origin/main)
Це два окремих графи:
- Жоден коміт з верхнього ланцюжка не є предком нижнього
- Історії не перетинаються взагалі
В такій ситуації rebase і merge не є «технічно неможливими» — вони логічно небезпечні. Саме тому Git зупиняється і вимагає від вас явного рішення, замість того щоб автоматично зшивати дві незалежні історії.
Найпоширеніші причини
У більшості випадків проблема не в rebase, а в тому, як з’явився репозиторій. Є кілька типових сценаріїв, які дуже часто призводять до unrelated histories.
1. Репозиторій ініціалізували двічі. Це найпоширеніший кейс — ви зробили git init локально, закомітили код, потім створили репозиторій на GitHub та підключили його як origin.
У результаті локальна історія починається з одного initial commit, а віддалена — з іншого. Для Git це два різних проєкти, навіть якщо файли виглядають однаково.
2. Імпорт коду + окремо створений repo. Це ще один класичний сценарій: код завантажили як zip, зробили перший коміт локально, але GitHub-репозиторій вже мав initial commit (README, .gitignore тощо). Тому файли можуть збігатись, але історії — ні.
3. Fork, mirror або ручне копіювання. За цим сценарієм, код був:
- Скопійований між проєктами
- Перенесений вручну або імпортований без збереження історії
Git бачить лише поточний стан файлів, але не бачить спільного минулого, тому вважає гілки незалежними.
4. Заміна remote
Іноді проблема з’являється після команди:
git remote set-url origin <new-url>
Якщо новий remote вказує на репозиторій з іншою історією, Git коректно відмовляється їх поєднувати без явного підтвердження.
В усіх цих випадках ключова причина одна: історії ніколи не були пов’язані, навіть якщо вам здається, що це «той самий код».
TL;DR: швидкі способи розв’язання
Якщо помилка вже з’явилась і потрібно швидко розблокувати роботу, є кілька перевірених варіантів. Вибір залежить від того, наскільки для вас важлива поточна історія комітів.
Варіант 1. Свідомо дозволити об’єднання (emergency-рішення)
git pull origin main --allow-unrelated-histories
Це найшвидший спосіб рухатись далі, але важливо розуміти наслідки:
- Це разовий свідомий крок, а не «нормальний» флоу
- Git створить merge commit
- Дві незалежні історії будуть просто «зшиті» разом
Цей варіант підходить, якщо потрібно терміново синхронізувати код і чистота історії не критична. Також ви маєте усвідомлювати, що сталось і чому зʼявляється ця помилка, тобто робити все в такому собі контрольованому середовищі.
Варіант 2. Якщо потрібен саме rebase
Якщо вам необхідно надалі працювати з rebase, потрібно один раз легально поєднати історії.
Спочатку зробіть merge з явним дозволом:
git merge origin/main --allow-unrelated-histories
Після цього з’явиться спільний коміт-предок, Git більше не вважатиме історії незалежними, а команда rebase почне працювати як очікується.
Це хороший компроміс між безпекою та чистотою історії.
Варіант 3. Правильний варіант для нового проєкту
Якщо проєкт щойно створений і локальна історія не має цінності, найчистіше рішення — повністю прийняти історію з remote.
git fetch origin
git reset --hard origin/main
Це безпечно, якщо у вас немає важливих локальних комітів, або ви готові їх втратити, або код уже є в remote.
Фактично ви кажете Git: «вважай віддалену історію єдиною правильною» — і проблема зникне.
Чому це часто з’являється саме під час rebase
Ця помилка майже завжди спливає саме під час rebase, і це не випадково. Ключовий момент у тому, що rebase працює значно суворіше, ніж здається на перший погляд.
merge працює за принципом «склеїти як є». Якщо Git може створити merge commit і якось поєднати дві гілки — він це зробить, навіть якщо історія виходить неідеальною. Саме тому merge часто сприймається як більш «поблажливий» механізм.
rebase працює інакше. Він переписує історію, ніби ваші коміти завжди існували поверх іншої гілки. Для цього Git мусить чітко знати:
- Де була спільна точка в історії
- Які коміти потрібно «перенести»
- В якому порядку їх відтворити
Без спільного коміту-предка цього зробити неможливо, адже якщо немає бази — немає від чого відраховувати зміни. Тому Git не намагається «вгадати» й зупиняється з помилкою замість того, щоб створити потенційно зламану або оманливу історію.
Саме через цю строгість rebase часто першим підсвічує проблему, яка насправді виникла значно раніше — ще в момент створення або імпорту репозиторію.