Когда использовать параметр слияния --no-ff в Git

Успешная модель Git Branching рекомендует использовать --no-ff при объединении веток:

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

Да, это создаст еще несколько (пустых) объектов коммитов, но выигрыш намного больше, чем эта стоимость. К сожалению, я не нашел способ сделать --no-ff поведение git merge по умолчанию еще нет, но так и должно быть.

Понимая рабочий процесс Git, однако, рекомендует не использовать --no-ff:

Таким образом, вы добавляете новое правило: "Когда вы объединяете в своей ветви функций, используйте –-no-ff чтобы заставить новый коммит ". Это делает работу, и вы идете дальше. [...]

--no-ff лейкопластырь, сломанный bisect, а также blame Тайны - это все признаки того, что вы используете отвертку в качестве молотка. [...]

Оба подхода кажутся разумными для разностных сценариев, но что считается "хорошей практикой"?

Когда вы используете --no-ff когда нет, почему?

3 ответа

Решение

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

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

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

В случае готовой ветви с одним коммитом не используйте --no-ffпросто перемотайте его вперед, потому что история будет намного проще и менее загромождена. Трудно утверждать, что --no-ff дает вам какие-либо преимущества в этом случае, потому что неинтересно видеть параллельную ветвь разработки с одним коммитом по сравнению с одним коммитом в последовательной строке:

# No fast-forward
$ git merge --no-ff awesome-feature
*   3aa649c Merge branch 'awesome-feature'
|\
| * 35ec88f Add awesome feature
|/
* 89408de Modify feature-001.txt and fix-001.txt
* c1abcde Add feature-003

# versus fast-forward
$ git merge awesome-feature
* 35ec88f Add awesome feature
* 89408de Modify feature-001.txt and fix-001.txt
* c1abcde Add feature-003

В случае готовой ветви с более чем одной фиксацией, вам решать, хотите ли вы сохранить факт, что разветвленная разработка происходила параллельно, а не последовательно. Я бы наверное использовал --no-ff для более чем одного коммита, просто чтобы я мог визуально увидеть эту разветвленную работу, и чтобы я мог легко манипулировать ею с помощью одного git revert -m 1 <sha-of-merge-commit> если бы мне пришлось.

# No fast-forward
$ git merge --no-ff epic-feature
*   d676897 Merge branch 'epic-feature'
|\
| * ba40d93 Add octocat.txt
| * b09d343 Add bye.txt
| * 75e18c8 Add hello.txt
|/
* 89408de Modify feature-001.txt and fix-001.txt
* c1abcde Add feature-003

# versus fast-forward
$ git merge epic-feature
* ba40d93 Add octocat.txt
* b09d343 Add bye.txt
* 75e18c8 Add hello.txt
* 89408de Modify feature-001.txt and fix-001.txt
* c1abcde Add feature-003

Посмотрите, как в этом случае быстрого слияния без дополнительной информации в самих сообщениях о коммитах трудно сказать, что последние 3 коммита фактически объединены в одну функцию?

Это действительно зависит от вашего рабочего процесса и от того, как вы используете ветки.

Допустим, у вас есть "master" и две ветки функций, "foo" и "bar", в разработке.

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

Но вы могли бы иметь другой рабочий процесс, если бы ветви, "foo" и "bar", ссылались на независимые модули в вашей системе.

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

Вам нужно решить, важна ли история слияния филиалов для вашего рабочего процесса.

И, следуя комментариям, я предпочитаю rebase, а также pull --rebase рабочий процесс.

Другие вопросы по тегам