Git не может объединить несвязанные истории, мелкий клон

Я мелко клонировал репо с глубиной 1 и создал локальную ветку разработки для разработки. После поднятия PR я получил конфликты слияния, поэтому я вытащил последний мастер и попытался слить его с веткой dev.

Подход 1:

  1. Когда я пытаюсь потянуть за ветку, она говорит fatal: refusing to merge unrelated histories
  2. Итак, я удалил локальный мастер и использовал переключатель для создания новой ветки git switch -c master origin/master
  3. Теперь, когда я пытаюсь объединить основную ветку с локальной для разрешения конфликтов слияния, я получаю сообщение об ошибке fatal: refusing to merge unrelated histories

Подход 2:

  1. То же самое до шага 2 в подходе 1.
  2. Я попытался выбрать фиксацию, которая вызвала конфликты слияния. Поскольку репозиторий поверхностно клонирован, он не имеет истории коммитов и выдает ошибку bad object.

Я пробовал –allow-unrelated-histories, было так много конфликтов слияния, которые приходилось исправлять вручную.

Как решить эту проблему и объединить master с моей веткой dev?

Попробуйте отменить освящение своей ветки git fetch --unshallow origin my/branch или --deepen, пока не увидите общий коммит между вашей веткой и master

LeGEC 31.10.2022 18:07

Какую команду вы использовали, чтобы «вытащить мастера»? Вы также использовали --depth=1 ?

LeGEC 31.10.2022 18:18

@LeGEC: может не иметь значения, что использовалось для вытягивания, в зависимости от того, где происходит неглубокий трансплантат. Могу поспорить, что здесь так и было.

torek 31.10.2022 21:19

При клонировании я использовал --depth=1. При вытягивании я не могу сделать вытягивание непосредственно на мастере, выдает ту же ошибку fatal: refusing to merge unrelated histories. Итак, я использовал git switch, чтобы получить последний мастер.

eoeo 01.11.2022 14:42
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
92
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Никогда1 не используйте --allow-unrelated-histories. Вместо этого углубите (или «неглубоко») ваш клон. Редактировать: согласно комментариям, вам также необходимо преобразовать свой клон в полный клон (в настоящее время это клон с одной ветвью, чего я должен был ожидать, поскольку при использовании --depth во время клонирования по умолчанию также создается клон с одной ветвью).

Слияние в Git зависит от трех коммитов, а не от двух:

  • есть ваш текущий коммит (он же HEAD), который будет представлять работу, проделанную с некоторой общей отправной точки;
  • есть какой-то другой коммит, который будет представлять работу, выполненную в какой-то другой ветке с той же общей отправной точки; и
  • есть третья фиксация, база слияния, которая является общей отправной точкой.

Когда вы запускаете git merge, аргумент, который вы предоставляете — обычно имя ветки, такое как feature или master — находит середину этих трех: «другой» или --theirs коммит. Текущая или --ours фиксация подразумевается тем, что вы проверили. Третий коммит, общую отправную точку, Git находит самостоятельно. Но Git нужна история, чтобы найти этот коммит.

История в репозитории Git — это не что иное, как коммиты в репозитории. У обычного, не поверхностного клона есть все коммиты2, поэтому у него есть вся история. Смысл поверхностного клонирования в том, чтобы намеренно опустить часть истории во имя целесообразности. Для некоторых целей это нормально (и, следовательно, на самом деле целесообразно). Для слияния это не нормально; не делай этого.

Если у вас уже есть неглубокий клон, например, потому что ваша система CI сделала его, рассмотрите возможность запуска:

git remote set-branches origin "*"
git fetch --unshallow

Первая команда преобразует клон в стандартный полный клон (отменяя одноветвистость). Обратите внимание, что вы можете ввести * без кавычек, но использование таких кавычек всегда должно работать.

Вторая команда перенаправляет обычную операцию git fetch таким образом, чтобы убрать поверхностность. Если окажется, что это требует слишком много системных ресурсов, вы можете в качестве альтернативы использовать git fetch --depth или git fetch --deepen для постепенного добавления дополнительных коммитов в неглубокий репозиторий, пока у вас не будет достаточно истории — достаточно коммитов — для git merge, чтобы найти общую отправную точку. Проблема с этим подходом заключается в том, что нет гарантии, насколько глубокой может быть эта глубина, а это означает, что нет правильного способа выбрать правильную глубину. Это, в свою очередь, подразумевает цикл, в котором вы многократно увеличиваете глубину до тех пор, пока она не станет «достаточной», и каждый раз использует все больше и больше системных ресурсов, чего, по-видимому, вы пытались избежать в первую очередь с помощью поверхностного клонирования.

Большинство систем CI, которые делают поверхностные клоны, предлагают вам способ принудительного создания полного клона в первую очередь (что в целом более эффективно, чем создание поверхностного клона, а затем его удаление). Поэтому, если проблема заключается в поверхностном клонировании, как в этом случае, просто не делайте этого в первую очередь.


1Правило для продвинутых пользователей Git: никогда не используйте --allow-unrelated-histories, пока не докажете, что это нормально.

2Помните, суть операции git clone заключается в копировании всех коммитов, но ни одного имени ветки. Для работы Git не нужны имена веток, но нужны коммиты. Нам — людям — не нравится использовать Git без имен веток, поэтому мы всегда заставляем Git создавать некоторые из них, хотя системы CI иногда не обращают на них внимания; мы используем имена веток и/или имена удаленного отслеживания (которые запоминают имена веток некоторых других репозиториев), чтобы найти интересные коммиты. Git также может использовать их, но может напрямую использовать необработанные хэш-идентификаторы, как работают эти системы CI.

Я сделал git fetch --unshallow на локальном мастере, а затем попытался выполнить git merge master в своей ветке разработки. Выдало ту же ошибку refusing to merge unrelated histories. Вишневый сбор коммита не сработал, как он сказал fatal: bad object HashID. Я дважды проверил хэш-идентификатор и сделал это в своей ветке разработки git cherry-pick hashID

eoeo 01.11.2022 14:40

Возможно, у вас тоже есть клон с одной веткой? Каков результат git config --get remote.origin.fetch?

torek 01.11.2022 14:42

Это дало такой вывод +refs/heads/u/myname/AnotherDevBranch:refs/remotes/origin/u/‌​myname/AnotherDevBra‌​nch. This AnotherDevBranch — моя ветка, не знаю, почему для нее установлено значение AnotherDevBranch.

eoeo 01.11.2022 14:53

должно ли это указывать на мастера вот так? +refs/heads/master:refs/remotes/master?

eoeo 01.11.2022 15:44

Ага, вот и оставшаяся проблема: да, у вас клон с одной веткой. Запустите git remote set-branches origin "*", чтобы преобразовать в полный клон, затем запустите git fetch, чтобы подобрать коммиты и создать соответствующие имена для удаленного отслеживания.

torek 02.11.2022 03:07

Другие вопросы по теме