Как именно работает git pull --allow-unrelated-history? - PullRequest
0 голосов
/ 23 февраля 2019

Правильно, поэтому я перебрал некоторые другие темы SO, а также проверил это: https://git -scm.com / docs / git-merge

Я понимаю, что--allow-unrelated-historyories позволяет объединить два проекта, однако я не понимаю, как именно это работает .

Работает ли это просто так?https://imgur.com/a/ZFVVs7s

На приведенном выше сайте git приведена следующая диаграмма:

      A---B---C topic
     /         \
D---E---F---G---H master

Однако мне кажется, что у них нет связанных историй, потому что ветка темыоткололся от 'E'.Даже если ветвь темы будет отделена от главной в «D», они все равно будут использовать ветвь «D».

Кто-нибудь сможет объяснить (желательно визуально), как именно работает история разрешенных взаимосвязей?Я пытаюсь сделать git pull, но один из членов моей команды отредактировал ветку, из которой я тяну, и теперь я должен использовать --allow-unrelated-history.

Спасибо!

Ответы [ 2 ]

0 голосов
/ 23 февраля 2019

Вы правы, что на вашей диаграмме (из git-scm.com / docs / git-merge ) показано слияние с общим коммитом предка.Стоит отметить, что это общий коммит; термин branch в Git довольно хитрый.(См. Что именно мы подразумеваем под "ветвью"? )

В любом случае, я думаю, это поможет, если вы забудете, что git pull даже существует.Все, что git pull делает, это запускает две разные команды Git для вас.Вам будет лучше, пока вы не разберетесь с Git, используя отдельные команды git fetch и git merge.(Обратите внимание, что git pull --rebase переключает вторую команду на git rebase, но мы не будем здесь вдаваться в подробности.) Есть несколько проблем с использованием git pull для запуска двух других команд.Одна из них заключается в том, что git pull использует странный синтаксис только для извлечения, отличный от всех других команд Git, включая git merge, который запускается git pull.То есть вместо git pull origin xyz вы будете запускать git merge origin/xyz.Чтобы увидеть, что это такое, вы должны запустить git log origin/xyz или git show origin/xyz и т. Д. Они всегда пишутся origin/xyz с косой чертой, кроме случаев использования git pull - поэтому не используйте git pull.:-) Давайте разберем его на две отдельные команды.

  • Первая команда git pull выполняется git fetch, которую вы можете запустить в любое время: git fetch вызовкакой-то другой Git спрашивает его, какие коммиты он имеет для вас, под какими именами (обычно это имена веток и тегов).Он собирает эти коммиты (и, конечно, их файлы) и для каждого из их имен ветвей создает или обновляет ваши имена для удаленного отслеживания.Так вот откуда взято origin/master, например: git fetch видит, что у них есть master, что их хозяин - коммит badf00d или что-то еще, и создает или обновляет ваш origin/master, чтобы запомнить: *Мастер 1045 * был badf00d последний раз, когда я проверял.

  • Вторая команда, которую git pull запускает для вас, - это то место, где находятся все интересные действия.Эта вторая команда должна не выполняться в любое старое время, в любой старой ветке, потому что, какая бы вторая команда у вас ни выполнялась, Git, эта должна быть в правой ветви:вы хотите слиться или тот, который вы хотите перебазировать.Я нахожу, что использование отдельных команд помогает здесь, потому что более ясно, что git merge повлияет на ветку current , даже если вы назовете что-то вроде origin/master.

Теперь, когда мы знаем, --allow-unrelated-histories - это действительно вариант git merge, давайте углубимся в git merge и посмотрим, что он делает.Сначала мы посмотрим, что он делает с общей отправной точкой, затем снова на то, что он делает без единицы.

Объединение - это объединение изменений, так как общееначальная точка

Рассмотрим приведенную выше диаграмму, которую я немного перерисую:

     A--B--C   <-- topic
    /
D--E--F--G   <-- master (HEAD)

Это указывает на то, что, кто бы ни работал над topic, он начал с проверкиout commit E.Возможно, в то время коммит E был последним коммитом на master:

D--E   <-- master, topic

С тех пор кто-то добавил два коммита на master, что составляет F и G, а кто-то - возможно, кто-то еще - добавил три коммита на topic, которые теперь являются цепочкой A-B-C (родительский коммит A равен E).

Каждый коммит представляет собой полный снимок всех исходных файлов.Так что в commit E есть все файлы - ну, все файлы, которые были у вас, когда вы или кто-то другой сделал коммит E - сохранялись в этой форме навсегда.Любые изменения, внесенные вами или кем бы то ни было в любые файлы из этого сохраненного состояния и сохраненные, скажем, при фиксации A, приводят к тому, что эти файлы переходят в новое состояние в A.Любые неизмененные файлы в A просто точно соответствуют файлам в E.

Длядля простоты, мы предположим, что здесь действуют два человека, «вы» и «они», и вы внесли изменения в master, что в итоге привело к фиксации G.Затем они сделали A до C.Итак, вы и они оба начали с того, что всегда сохраняется в коммите E.Вы получили то, что вы сохранили навсегда в G.Таким образом, Git может узнать , что вы изменили с помощью простого git diff, чтобы сравнить коммит E с коммитом G.Аналогично, они оказались на C, поэтому Git может узнать, что они изменили на аналогичное простое git diff, сравнивая E против C:

  • git diff --find-renames <em>hash-of-E hash-of-G</em>: что вы изменили
  • git diff --find-renames <em>hash-of-E hash-of-C</em>: что они изменили

Затем Git извлекает файлы из commit E, то есть с чего вы оба начали, объединяет ваши изменения в этих файлах и создает новый коммит с объединенными изменениями в них.Это определяет, какие файлы / содержимое входят в коммит H:

     A--B--C   <-- topic
    /       \
D--E--F--G---H   <-- master (HEAD)

Первый родитель нового коммита H - G, который был кончиком master и является вашей веткойпроверено.Его второй родитель - C, тот, которого вы сказали git merge для слияния.

Обратите внимание, что когда Git делает все это объединение изменений, он легко справляется со всеми файлами, которые точноодинаковые в обоих подсказках ветвления, потому что независимо от того, что было в базе объединения, оба подсказки совпадают, поэтому оба файла одинаковы, и любой из них работает нормально.Это также легко сделать, если вы изменили файл X, а они этого не сделали, и где они изменили файл Y, а вы нет, потому что, опять же, он может просто взять вашу или их версию этих файлов.Только там, где вы по-разному касались одного и того же файла, Git должен усердно работать.

Несвязанные истории

Несовместимые истории возникают, когда нет общая связь между двумя наборами коммитов:

A--B--C   <-- master (HEAD)

J--K--L   <-- theirs

Ваши коммиты начинаются с C и работают в обратном направлении, заканчиваясь A.Коммиты не приходят раньше, чем A: A не имеет родителей.

Их коммиты начинаются, в данном случае, с L (я пропустил много писем, чтобы покинуть комнату, чтобы вставить наше слияние).Родитель L - K, а родитель K - J, но у J также нет родителей.Так что общей отправной точки нет вообще.

Если вы скажете Git объединить их, Git просто притворится, что есть.Предполагаемая начальная точка имеет файлы no .Git работает:

  • git diff <em>empty-tree hash-of-C</em>: что вы изменили
  • git diff <em>empty-tree hash-of-L</em>: что они изменили

Конечно, что вы изменили, из этогоdiff, это то, что вы добавили каждый файл (это в вашем коммите C).Что они изменили, так это то, что они добавили каждый файл (это в их коммите L).

Если файлы имеют разные имена, это разные файлы и проблем нет: Git принимаеттвой или их.Если у них одинаковые имена, но одинаковое содержимое, здесь тоже нет конфликта: Git может просто взять ваши (или их).Проблемы возникают для всех файлов, у которых у вас и у них одинаковое имя, но разное содержимое.Что касается Git, вы взбили свои с нуля, как и они, так что все конфликтует.Вы должны выбрать выигрышное содержимое или создать новый файл из входных данных «все конфликты».

Как только вы разрешите любой из этих конфликтов и запустите git merge --continue, чтобы завершить Git, Git выполняет коммит слияния как обычно:

A--B--C--D   <-- master (HEAD)
        /
J--K---L   <-- theirs

У нового коммита есть два родителя, C и L, и он навсегда сохраняет созданный вами снимок, исправляя конфликты, о которых сообщал Git, и другие файлы, которые были точното же самое в C и L или только в C, или только в L.

(«Навсегда» слишком сильно: сохраненные файлыдлится только до тех пор, пока сам коммит. Однако по умолчанию каждый коммит живет вечно. Если вы делаете коммит исчезающим, файлы тоже.)

0 голосов
/ 23 февраля 2019

Объединение несвязанных историй работает следующим образом: вы представляете, что перед корнем каждой истории есть общий предок, без содержания вообще.Это база слияния.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...