Почему git выполняет ускоренное слияние по умолчанию?

615

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

Я начал свой новый проект с помощью git и закончил свою первую функцию. При объединении этой функции я понял, что git использует ускоренную перемотку вперед, т.е. Применяет мои изменения непосредственно к ведущей ветке, если это возможно, и забывает о моей ветке.

Так думать в будущее: я единственный, кто работает над этим проектом. Если я использую подход git по умолчанию (быстрое слияние), моя история приведет к одной гигантской ветки мастера. Никто не знает, что я использовал отдельную ветку для каждой функции, потому что в итоге у меня будет только эта гигантская ветвь мастера. Не будет ли это непрофессиональным?

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

  • 37
    Примечание: см. Также sandofsky.com/blog/git-workflow.html и избегайте « no-ff » с его « фиксацией с помощью контрольной точки», которая разбивает пополам или обвиняет.
  • 15
    Вы сожалеете об использовании Git в одном проекте?
Показать ещё 12 комментариев
Теги:
git-branch
git-merge
fast-forward

2 ответа

728
Лучший ответ

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

Предупреждение. Непрерывная пересылка также имеет потенциальные побочные эффекты. Пожалуйста, просмотрите https://sandofsky.com/blog/git-workflow.html, избегайте "no-ff" с его "контрольной точкой", которые ломают биссект или обвиняют, и тщательно подумайте, должно ли оно как ваш подход по умолчанию для master.

Изображение 7655
(Из nvie.com, Винсент Дриссен, post " Успешная Git ветвящаяся модель ")

Включение готовой функции при разработке

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

$ git checkout develop
Switched to branch 'develop'
$ git merge --no-ff myfeature
Updating ea1b82a..05e9557
(Summary of changes)
$ git branch -d myfeature
Deleted branch myfeature (was 05e9557).
$ git push origin develop

Флаг --no-ff заставляет слияние всегда создавать новый объект фиксации, даже если слияние может выполняться с быстрой перемоткой вперед. Это позволяет избежать потери информации об историческом существовании ветки признака и группировать вместе все фиксации, которые вместе добавили эту функцию.

Jakub Narębski также упоминает config merge.ff:

По умолчанию Git не создает дополнительное объединение при объединении коммита, являющегося потомком текущего коммита. Вместо этого кончик текущей ветки быстро перенаправляется.
Когда установлено значение false, эта переменная сообщает Git создать дополнительное слияние в таком случае (эквивалентно предоставлению опции --no-ff из командной строки).
Если установлено значение "only", допускаются только такие быстрые слияния (эквивалентно предоставлению опции --ff-only из командной строки).


Ускоренная перемотка вперед по умолчанию:

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

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

В этом случае вы можете установить этот тип файла конфигурации:

[branch "master"]
# This is the list of cmdline options that should be added to git-merge 
# when I merge commits into the master branch.

# The option --no-commit instructs git not to commit the merge
# by default. This allows me to do some final adjustment to the commit log
# message before it gets commited. I often use this to add extra info to
# the merge message or rewrite my local branch names in the commit message
# to branch names that are more understandable to the casual reader of the git log.

# Option --no-ff instructs git to always record a merge commit, even if
# the branch being merged into can be fast-forwarded. This is often the
# case when you create a short-lived topic branch which tracks master, do
# some changes on the topic branch and then merge the changes into the
# master which remained unchanged while you were doing your work on the
# topic branch. In this case the master branch can be fast-forwarded (that
# is the tip of the master branch can be updated to point to the tip of
# the topic branch) and this is what git does by default. With --no-ff
# option set, git creates a real merge commit which records the fact that
# another branch was merged. I find this easier to understand and read in
# the log.

mergeoptions = --no-commit --no-ff

OP добавляет в комментарии:

Я вижу некоторый смысл в быстрой перемотке для [короткоживущих] ветвей, но, делая это действие по умолчанию, означает, что Git предполагает, что у вас часто есть [недолговечные] ветки. Разумные?

Ответ Джефроми:

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

Для меня короткоживущая ветвь - это та, которую я создаю, чтобы упростить некоторую операцию (переустановка, скорее всего, или быстрое исправление и тестирование), а затем сразу же удалить один раз, m done.
Это означает, что, скорее всего, следует вложить в ветвь темы, которую она разветвляла из, и ветвь темы будет объединена как одна ветка. Никто не должен знать, что я сделал внутренне, чтобы создать серию коммитов, реализующих данную функцию.

В более общем плане я добавляю:

это действительно зависит от вашего рабочего процесса разработки:

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

См. " Когда вы должны вступить?

Собственно, когда вы рассматриваете модель ветки Mercurial, она находится в центре одной ветки на репозиторий (даже если вы можете создать анонимные заголовки, закладки и даже названные ветки)
См. Git и Mercurial - Сравнить и Контраст.

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

  • 0
    Вау, это было быстро. ;) Я знаю о параметре --no-ff, но о быстрой перемотке узнаю только после того, как испортил свою функцию. Я вижу некоторый смысл в перемотке вперед для короткоживущих ветвей, но если сделать это действием по умолчанию, это означает, что git предполагает, что у вас чаще всего есть такие короткоживущие ветки. Разумно?
  • 0
    @Florian: я считаю, что это разумный взгляд на процесс. Я добавил пример конфигурации, которая настроит способ управления слиянием с мастером.
Показать ещё 26 комментариев
39

Позвольте мне немного расширить VonC очень полный ответ:


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

Обратите внимание, что полезность ветвей функций и наличие нескольких ветвей в одном репозитории приходят только позже, с более широким использованием VCS с хорошей поддержкой слияния и с попытками различных рабочих процессов на основе слияния. Вот почему, например, Mercurial изначально поддерживал только одну ветвь в репозитории (плюс анонимные подсказки для отслеживания удаленных веток), как видно из более ранних версий "Mercurial: The Definitive Guide".


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

НТН

  • 0
    Относительно ветвей функций из стабильных выпусков: что, если функция, которую я разрабатываю для следующего выпуска, зависит от изменений другой функции, которую я уже разработал и слил в мастер? Конечно, это означает, что я должен создать эту вторую ветвь функций из master?
  • 1
    @dOxxx: Да, есть исключения, например, когда одна ветка строится на другой (либо напрямую, либо после слияния предыдущего в мастер).

Ещё вопросы

Сообщество Overcoder
Наверх
Меню