Почему git fast-forward сливается по умолчанию?

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

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

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

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

2 ответов


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

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

alt text
(от nvie.com,Винсент Дриссен, post"успешная модель ветвления Git")

включение готовой функции на develop

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

$ 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 флаг заставляет слияние всегда создавать новый объект фиксации, даже если слияние может быть выполнено с быстрой перемоткой вперед. Это позволяет избежать потери информации об историческом существовании ветви объекта и группирует все коммиты, которые вместе добавили объект.

Якуб Narębski и упоминает the конфиг merge.ff:

по умолчанию Git не создает дополнительную фиксацию слияния при слиянии фиксации, которая является потомком текущей фиксации. Вместо этого наконечник текущей ветви перенаправляется.
Когда установлено значение false, эта переменная говорит Git создать дополнительную фиксацию слияния в таком случае (эквивалентно предоставлению из командной строки).
Когда установлено значение'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 предполагает вас... частое [недолго] филиалы. Разумно?

Jefromi ответы:

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

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

больше вообще, добавляю:

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

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

в разделе "когда вы должны ветке?"

на самом деле, когда вы считаете модель ветви Mercurial, она в своей основе один ветку в репозитории (даже если вы можете создать анонимные главы, закладки и даже названные ветви)
См. "Git и Mercurial-сравнить и контраст".

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


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


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

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


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

HTH