Как git сливается после работы вишневого забора?

Предположим, что у нас есть ветвь master.

Затем мы создаем a newbranch

git checkout -b newbranch

и сделайте две новые коммиты для newbranch: commit1 и commit2

Затем переходим к мастеру и делаем cherry-pick

git checkout master
git cherry-pick hash_of_commit1

Заглядывая в gitk, мы видим, что commit1 и его вишневая версия имеют разные хеши, поэтому технически они представляют собой две разные фиксации.

Наконец, мы объединяем newbranch в master:

git merge newbranch

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

Действительно ли git делает интеллектуальный анализ содержимого фиксации при слиянии и принимает решение о том, что изменения не должны применяться дважды, или эти коммиты помечены как внутренние вместе?

Ответ 1

Короткий ответ

Не волнуйтесь, Git обработает его.

Длинный ответ

В отличие от, например, SVN 1 Git не сохраняет фиксации в дельта-формате, но на основе снимков 2,3. В то время как SVN наивно попытается применить каждый объединенный коммит как патч (и с ошибкой, по той причине, что вы описали), Git, как правило, может обрабатывать этот сценарий.

При слиянии Git будет пытаться объединить снимки обеих записей HEAD в новый моментальный снимок. Если часть кода или файла идентична в обоих моментальных снимках (т.е. Поскольку фиксация уже выбрана вишней), Git не коснется ее.

Источники

1Пропустить-Deltas в Subversion
2Git Основы
3Объектная модель Git

Ответ 2

После такого слияния вы можете дважды забирать вишни в истории.

Решение, чтобы предотвратить это, я цитирую из статьи статьи, в которой рекомендуется, чтобы ветки с дублирующимися (вишневыми) коммитами использовали rebase перед слиянием:

git merge after git cherry-pick: избегая повторных коммитов

Предположим, что у нас есть главная ветвь и ветка b:

   o---X   <-- master
    \
     b1---b2---b3---b4   <-- b

Теперь нам срочно нужны коммиты b1 и b3 в master, но не остальное совершается в b. Итак, что мы делаем, это проверка основной ветки и захват вишни b1 и b3:

$ git checkout master
$ git cherry-pick "b1 SHA"
$ git cherry-pick "b3 SHA"

Результат:

   o---X---b1'---b3'   <-- master
    \
     b1---b2---b3---b4   <-- b

Предположим, что мы делаем еще одну фиксацию на master, и получаем:

   o---X---b1'---b3'---Y   <-- master
    \
     b1---b2---b3---b4   <-- b

Если бы мы теперь объединили ветвь b в master:

$ git merge b

Мы получили бы следующее:

   o---X---b1'---b3'---Y--- M  <-- master
     \                     /
      b1----b2----b3----b4   <-- b

Это означает, что изменения, введенные b1 и b3, появятся дважды в история. Чтобы избежать этого, мы можем переустановить вместо слияния:

$ git rebase master b

Что даст:

   o---X---b1'---b3'---Y   <-- master
                        \
                         b2---b4   <-- b

Наконец:

$ git checkout master
$ git merge b

дает нам:

   o---X---b1'---b3'---Y---b2---b4   <-- master, b