Как 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