Это направление или порядок слияния / перебазировки делают разницу в Git? - PullRequest
0 голосов
/ 19 сентября 2018

Допустим, вы извлекаете данные из удаленного репозитория, пока работаете над веткой функций, а новые ветки добавляются в основную ветку.

Вы заканчиваете работу над веткой функций, фиксируете свои изменения и затем объединяете / перебазируете их в мастер.Где в основной ветке вставляются коммиты функций, до или после вытащенных коммитов?Куда они вставляются, если вы никогда не выполняли тягу?Будет ли он иметь такой же результат?

Кроме того, что произойдет, если вы слите / перебазируете мастер в ветке функций, а не наоборот?Где мастер вставляется в ветку объектов, если вы слили / перебазировали до или после вытягивания?Будет ли это иметь тот же результат?Будет ли его история отличаться от вышеупомянутого слияния / перебазирования функции в мастер?

Вкратце, у направления слияния и / или порядка слияния будут разные результаты в результате слияния?Я подозреваю, что это не имеет значения.

ASIDE : На этот вопрос может быть легко ответить для того, кто его посещает, но с сотнями, если не тысячами, документации и учебных ресурсов, я никогда не видел егоадресовано напрямую.Не зная ответа, Git может быть очень запутанным для понимания.

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

Другие инструменты отслеживания версий гораздо лучше справляются с абстрагированием этой когнитивно-коррозийной операции.

Ответы [ 3 ]

0 голосов
/ 19 сентября 2018

Вы заканчиваете работу над веткой функций, фиксируете свои изменения и затем объединяете / перебазируете их в мастер.

Где в основной ветке вставляются коммиты функций, до или после вытащенных коммитов?

После: при слиянии / перебазировании будет учитываться текущее состояние главной ветви.
Если эта ветвь эволюционировала (с вытягиванием), тогда при слиянии / перебазировании будет использоваться текущий главный HEAD(который теперь ссылается на извлеченные коммиты)

Куда они вставляются, если вы никогда не выполняли извлечение?

То же самое: он будет использовать текущий главный HEAD (который не отражает никаких новых коммитов, поскольку не было выполнено извлечение)

Будет ли он иметь тот же результат?

Нет, учитывая, что мастер HEAD различен в обоих случаях.

Кроме того, что произойдет, если вы объедините / перебазируете мастер в ветвь функций, а не наоборот??

Во-первых, не надо: это не лучшая практика.
Но если вы это сделаете, то слияние / перебазирование будет использовать функцию HEAD.

Гдемастер вставляется в ветку объектов, если вы слили / перебазировали до или после вытягивания?Будет ли он иметь тот же результат?

Тот же результат, так как в обоих случаях он использует функцию HEAD, которая не изменилась, когда вы выполняете (или не делаете) извлечение мастера.

0 голосов
/ 19 сентября 2018

TL; DR

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

Этоужасная ошибкаGit работает в порядке графиков , а не в хронологическом порядке.Когда порядок графика хронологический - что иногда, но не всегда - , тогда работает нормально.

Long

(я даже не буду касаться ребазздесь. Для правильного обсуждения перебазирования см. более ранние публикации. Я просто собираюсь сосредоточиться на симметрии в слиянии и местах, где могут показать швы.)

Более кратко, сделайтеНаправление слияния и / или порядок слияния имеют разные результаты в результате слияния?Я подозреваю, что это не имеет значения.

Ответ и нет, и да.

Чтобы понять почему это ответ, вам нужно понять несколькоо Git.

Во-первых, давайте рассмотрим, как Git обрабатывает коммиты, в отличие от того, сколько других делают это (большинство других? все остальные? должна быть хотя бы одна другая VCS, которая делает это тоже ...),В системах контроля версий процесс создания коммита в ветви добавляет новый коммит к ветви;но в Git набор ветвей, которые содержат коммит после его выполнения , может быть и может динамически изменяться.Таким образом, сделанный после этого коммит не зависит от какой-либо ветви и может, если хотите, быть выполнен на no ответвлении.

В Mercurial дляНапример, это совершенно невозможно.В то время как Mercurial во многом очень похож на Git, существование коммита требует существования его ветви.Фиксация сделана на этой ветви, и навсегда часть этой ветви.Это ветвь only , которая содержит фиксацию: коммит постоянно прикрепляется к своей ветке.

В Git и Mercurial каждый коммит имеет уникальный идентификатор, и каждый коммит хранит уникальныйИдентификатор его родительского (единственного) коммита, если это обычный коммит.Следуя этой обратной цепочке, начиная с last commit и работая в обратном направлении, мы можем найти историю коммитов на ветке:

...  <-grandparent  <-parent  <-child

В Mercurial эти коммиты навсегдав их ветке, поэтому мы можем написать название ветви слева:

branch-A:  ...--I--J

Найти последний коммит в Mercurial легко, поскольку коммиты имеют простой порядковый номер в локальном репозитории (вместе с уникальным идентификатором хеша)используется для совместного использования между репозиториями).

В Git ветка names является подвижной.Перед тем как коммит J существует, имя branch-A хранит необработанный хеш-идентификатор коммита I:

...--H--I   <-- branch-A

При создании нового коммита Git просто записывает хэш-идентификатор нового коммита в имя ветви, так что ветвь указывает на новый коммит:

...--H--I--J   <-- branch-A

Слияние - это и существительное, и глагол

В управлении версиями объединение , глагол или объединить некоторые коммиты, это процесс.Результат - по крайней мере, как в Git, так и в Mercurial - это коммит слияния , где мы используем слово слияние в качестве прилагательного, модифицирующего коммит , или для краткости, слияние (существительное).

Что делает коммиты слияния be коммиты слияния в том, что они имеют двух родителей, приносящих две линии развитиявместе:

...--I--J
         \
          M
         /
...--K--L

ОнОпять же, Git и Mercurial в основном одинаковы, с одним действительно важным отличием: в Mercurial коммит слияния находится конкретно на одной ветви, которая является той ветвью, на которой вы находитесь, когда запускаете hg merge.Коммиты, включая коммиты слияния, постоянно прикрепляются к их ветвям.Как только процесс слияния завершен и коммит слияния существует, этот коммит слияния находится в этой одной ветви.В Git коммит слияния идет на текущую ветку, но поскольку мы можем переместить name , в некотором смысле это не имеет значения.

Но мы должны рассмотреть обе части:часть глагола, , чтобы объединить , а затем близко к части существительного, объединение .(Помимо: Git также позволяет коммитам слияния иметь более двух родителей, в то время как Mercurial ограничивает каждое слияние двумя родителями. Нет ничего такого, что эти фанки слияния, которые Git называет слияниями осьминога , могутсделать то, что вы не можете сделать с помощью серии попарных слияний, но в некоторых случаях слияние осьминога может показывать намерение более четко.)

Чтобы объединить, глагол

Предположим, например, что branch-A и branch-B были такими до слияния:

...--I--J   <-- branch-A

...--K--L   <-- branch-B

Прежде чем мы сможем объединить их, мы должны отследить обе истории назад достаточно далеко, чтобы найти слияние base , общий коммит, от которого эти две линии развития расходились.(Это верно и в Mercurial.) Итак, давайте добавим немного больше:

       I--J   <-- branch-A
      /
...--H
      \
       K--L   <-- branch-B

Здесь, коммит H является общей отправной точкой.В Git commit H находится на в обеих ветвях одновременно (но не в Mercurial).Тем не менее, обе системы управления версиями выполняют процесс для объединения практически одинаково: вы начинаете с выбора одного коммита для проверки, такого как коммит J с использованием git checkout branch-A или hg update branch-A.Затем вы выбираете другой коммит, используя команду merge глагол: git merge branch-B или hg merge branch-B.VCS находит соответствующую базу слияния, то есть commit H, и сравнивает содержимое H с содержимым J, чтобы увидеть, что you изменилось:

git diff --find-renames <hash-of-H> <hash-of-J>   # what we changed

и повторяет то же сравнение, чтобы найти то, что они изменили:

git diff --find-renames <hash-of-H> <hash-of-L>   # what they changed

Git объединяет эти изменения в одно большое "все изменения", применяет эти изменения к base (commit H) и делает новый коммит.

(Mercurial делает то же самое, хотя есть некоторые очень важные различия с точки зрения того, как Mercurial знает о переименованиях. Это имеет значение, только если вы переименовалинекоторые файлы, начиная с базы слияния. Если у вас есть переименованные файлы, и у вас есть конфликт переименования / переименования, порядок слияния становится очень важным. Но давайте предположим, что проблем с переименованием нет.)

Самое интересное здесь то, что вы можете контролировать как объединяются изменения.В Git вы делаете это с помощью стратегии слияния и расширенных аргументов стратегии ;в Mercurial вы делаете это с помощью выбранного инструмента слияния .Если вы используете «нашу» стратегию / инструмент, VCS полностью игнорирует их изменения: объединенные изменения - это просто ваши изменения, поэтому VCS выполняет новый коммит слияния, используя тот же код как в текущем коммите.Здесь очевидно, что порядок слияния имеет значение: если мы игнорируем их изменения, нам лучше всего быть уверенными, кто "мы"!

Даже без "нашей" стратегии могут возникнуть конфликтымежду вашими изменениями и их изменениями.Если так, то и Git, и Mercurial могут сказать: предпочитают мой или предпочитают их .Это даст разные результаты, поэтому и здесь порядок слияния имеет значение.Конечно, на данный момент есть симметричный вариант: выберите мой или выберите их .Если вы поменялись ролями, вы можете поменять параметры, поэтому, хотя порядок важен, он менее важен.

Слияние, существительное

Давайте предположим, что нет никаких конфликтов и никаких особых наших / их событий, и запустим git checkout branch-A; git merge branch-B.Если все идет хорошо, VCS делает коммит слияния M со своими двумя родителями:

       I--J
      /    \
...--H      M   <-- branch-A
      \    /
       K--L   <-- branch-B

В Mercurial порядок слияния здесь имеет значение, потому что как только коммит сделан M, он привязывается к еговетка навсегда.Но Git позволяет нам перемещать имена ветвей по факту.Мы можем сделать M таким, оставить его там, где он есть, толкнуть branch-A на один шаг назад, чтобы снова указать J, а затем переместиться на branch-B вперед, чтобы указать M, давая:

       I--J   <-- branch-A
      /    \
...--H      M   <-- branch-B
      \    /
       K--L

, что в значительной степени совпадает с тем, что мы получили бы, если бы сделали 1204 *.Таким образом, похоже, что здесь порядок слияния не имеет значения (при условии, что во время части глагол не было зацепок).Но здесь на диаграмме чего-то не хватает, и это понятие first и not-first родителей!

first родитель слиянияcommit M, как в Git, так и в Mercurial, является родителем "той же ветки".То есть, поскольку мы выполняли коммит J, когда мы запустили слияние, первый родительский элемент M - это коммит J.Это оставляет L в качестве второго родителя.Если мы переместим метки веток в Git, мы можем сказать, что сделали это, потому что первый и второй родители все еще будут в другом порядке.

Итак, мы видим здесь, что для Git, даже когда для слияния У глагола нет проблем с упорядочением, результирующий коммит слияния (прилагательное или существительное) действительно имеет порядок.Вы, пользователь, должны решить, имеет ли значение этот заказ для вас.Если нет, симметрия доступна.Если порядок родительского коммита имеет значение, направление / порядок слияния в Git так же критичен, как и в Mercurial.

График является ключом

В любой системе контроля версий на основе графа- следовательно, и в Git, и в Mercurial - график является историей.В частности, в Git нет такой вещи, как история файлов; график - это не только история primary , это история only .(Mercurial хранит данные файла более обычным способом, поэтому существует история файлов истории и , но история файлов в любом случае бесполезна без истории изменений.)

Чтобы иметь возможностьчтобы понять, что делает Git и почему, вам нужно знать достаточно теории графов, чтобы ездить или ездить на общественном транспорте по городу.Это не так уж много, но если вы не понимаете, что у Git есть эти односторонние железнодорожные пути / улицы / мосты, ведущие от last к обратному направлению к first ,многие вещи не будут иметь смысла.Git начинается в конце и работает обратно к началу.Имена ветвей приводят вас к графику в конце подсказки.Все остальное является функцией графа фиксации.

0 голосов
/ 19 сентября 2018

При слиянии как удаленные, так и ваши локальные коммиты полностью сохраняются без изменений, и коммит слияния ссылается на них обоих.

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

Для получения дополнительной информации о слиянии и разнице в перебазировании прочитайте этот ответ В чем разница между «git merge» и «git rebase»

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