Слияние совершают первый и второй родители - PullRequest
0 голосов
/ 20 мая 2018

На уроке Udacity, охватывающем относительные ссылки на коммиты, говорится:

^ указывает на родительский коммит, ~ указывает на первый родительский коммит

Основное различие между ^ и~ это когда коммит создается из слияния.У фиксации слияния есть два родителя.При коммите слиянием ссылка ^ используется для обозначения первого родителя коммита, а ^ 2 - второго родителя.Первый родитель - это ветвь, в которой вы работали, когда вы запустили git merge, а второй родитель - это ветвь, которая была объединена.

На основе следующего вывода команды git log --oneline --graph в командной строке:

graph

Коммит с SHA f69811c равен HEAD ~ 4 ^ 2 относительно коммита (самый верхний с указателем головы) 9ec05ca.Второй родительский коммит 1a56a81 является f69811c, и урок объясняет это: «HEAD ~ 4 ссылается на четвертый родительский коммит текущего, а затем ^ 2 говорит нам, что это второй родительский коммит слияния (тот, который был объединен). "

Судя по тексту урока, указанному желтым цветом, e014d91 является первым родителем 1a56a81, потому что это родитель с той же ветвью, что и слияниеcommit.

Исходя из этой информации, какое отношение будет e6c65a6 к 1a56a81?

Я не думаю, что это также второй родитель (если может быть несколько первыхи вторые родители ...), хотя это была также ветвь, которая была объединена с мастером, потому что этот ответ был отклонен в викторине урока.

Кроме того, если я прав, e014d91 это *Первый родитель 1034 *, каково отношение 2097521 и 3772ab1 к 1a56a81 (может показаться, что они также являются первыми родителями, опять же, если коммит слияния может фактически иметь несколько родителей)?

Ответы [ 2 ]

0 голосов
/ 20 мая 2018

Я думаю, что это может помочь просмотреть некоторые альтернативные представления графа.

Рассмотрим этот очень простой ромбовидный граф, с более поздними коммитами, нарисованными выше, а более ранними коммитами, нарисованными ниже:

  D
 / \
B   C
 \ /
  A

Здесь D может быть чрезвычайно укороченным хеш-идентификатором коммита слияния, при этом B и C являются его двумя входными данными (два родителя, в терминологии Git).A является (одним, единственным) родителем как B, так и C.В результате B и C являются братьями и сестрами, или были бы, если бы Git использовал эту концепцию напрямую: оба имеют одного и того же родителя, поэтому они должны быть братом и сестрой (или двумя братьями или двумя сестрами)или что угодно).Но Git обычно не говорит о коммитах таким образом - его обычно интересуют только непосредственные отношения родитель / потомок.

Мы могли бы - и git log --graph делает - также нарисовать это как:

*    d...... fourth message
|\
| *  c...... third message
* |  b...... another message
|/
*  a...... some commit message

Как и человеческие дети, у "детей" Гита может быть несколько родителей.Однако наиболее типичным случаем является наличие только одного родителя, и в этом случае родитель является первым, последним и единственным родителем.Вы можете назвать его - например, C^1 - это A - но в этом нет реальной необходимости.Нет C^2, и запрос об этом просто выдаст вам ошибку.

В сообщениях StackOverflow мне нравится рисовать мои графики с более ранними коммитами в слева и более поздними в right , вот так:

  B
 / \
A   D   <-- master (HEAD)
 \ /
  C   <-- develop

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

Любой коммит с не менее двумя родителями называется merge commit .Здесь используется слово merge как прилагательное, изменяющее commit .Мы также часто будем видеть это как слияние , используя слово merge как существительное.Как отмечает ElpieKay, коммит слияния может иметь более двух родителей, но эти слияния осьминога (как их называет Git) не делают ничего, что вы не можете сделать с помощью только парных слияний, поэтому они в основном простодля хвастовства.:-) Если у вас есть слияние с тремя или более родителями, вы можете пронумеровать их всех.Единственное специальное отличие, которое делает Git сам по себе, - это родительский элемент first , хотя, используя флаг --first-parent для различных команд Git, таких как git log.

, git merge, что смущаеткоманда не должна делать коммит слияния.Он состоит из двух частей, которые я люблю называть слиянием как глагол - актом объединения работы - и последующим совершением коммита.Коммит, который он делает, является коммитом слияния , если вы не укажете ему И, как будто это уже не сбивало с толку, несколько дополнительных команд Git выполняют слияние как глагол , не производя коммит слияния .Поэтому важно иметь в виду различие между формой глагол , для слияния и формой существительного или прилагательного.

Стоит отметить еще несколько пунктов:

  • Все коммиты - все объекты Git на самом деле - доступны только для чтения.Как только фиксация сделана, ее уже нельзя изменить, потому что ее хэш-идентификатор - как бы его истинное имя - вычисляется путем запуска всех лежащих в его основе данных через хэш-функцию.Если бы вы как-то изменили хотя бы один бит внутри коммита, вы бы получили новый и другой хэш и, следовательно, новый и другой коммит.

  • Поскольку родитель или родители существуюткогда ребенок сделан, ребенок может записать родителей.

  • Но так как его ребенок или дети еще не существуют, когда родитель создан, родитель не может записать своих детей.

  • Именно эти обратные родительские <- дочерние </em> связи формируют граф фиксации. 1

ThisЗначит этоВсе внутренние ссылки Git всегда назад .Git должен начинаться с последнего , дочернего элемента, фиксировать и работать в обратном направлении.Вот почему ветви имена , такие как master, всегда указывают на tip commit ветви.Поскольку Git работает в обратном направлении, один коммит за раз, слияния, в которых есть два или более родителей, представляют проблему: Git может вернуться только от ребенка к одному из родителей.Обычное решение этой проблемы в Git - поместить всех родителей в очередь, а затем работать с первым коммитом в очереди.

Флаг --first-parent указывает Git ставить только первый родитель в очередь, игнорируя второго родителя (и любых дополнительных родителей, если это слияние осьминога).Это позволяет Git обходить график коммитов без необходимости иметь более одного коммита за раз.


1 Математически любой граф G являетсяопределяется набором вершин V и ребер E , которые мы записываем как G = (V, E) .Граф может быть направленным , а Git - это: ссылки от вершины к вершине идут только одним путем.Такие ребра называются дугами .В нашем случае я предпочитаю называть вершины узлами; - это сами фактические коммиты, и каждый узел содержит список всех своих исходящих дуг, т. Е. Хэш-идентификаторы родительских коммитов.

Граф коммитов в Git не только направлен , но и ацикличен , что означает, что если мы начнем с любого коммита и пройдемся по графику, мы никогда не вернемся к тому же коммиту,Другими словами, ни один родитель не может быть своим собственным ребенком.Это полезное и важное свойство для различных преобразований графа, которые выполняет Git, поэтому мы иногда говорим о графе фиксации Git как DAG , что сокращенно от Directed Acyclic Graph .График коммитов, или коммит DAG, представляет все снимки, которые вы когда-либо делали.

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

0 голосов
/ 20 мая 2018

e6c65a6 - первый родитель 1a56a81 (f69811c), первый родитель.

3772ab1 - первый родитель 1a56a81 (e014d91), первый родитель (2097521) 1-й родитель.

коммитможет иметь нулевого родителя.Это корневой коммит.

Коммит может иметь 2 родителя, что является результатом слияния одной ветви с другим путем «истинного слияния».

Коммит может иметь более 2parent, который является результатом слияния 2 или более веток в одну ветку одновременно, способом «слияния осьминога».

Чтобы узнать родительские коммиты коммита X, вы можете использовать:

git log -1 X --pretty=%P

или

git log -1 X --pretty=raw

или

git cat-file -p X

и т. Д.

...