В чем разница между `git merge` и` git merge --no-ff`? - PullRequest
809 голосов
/ 30 января 2012

Используя gitk log, я не смог определить разницу между ними. Как я могу наблюдать разницу (с помощью команды git или какого-либо инструмента)?

Ответы [ 5 ]

917 голосов
/ 30 января 2012

Флаг --no-ff не позволяет git merge выполнить «ускоренную перемотку вперед», если обнаружит, что ваш текущий HEAD является предком коммита, который вы пытаетесь объединить.Быстрая перемотка вперед - это когда вместо создания коммита слияния git просто перемещает указатель ветки, чтобы указать на входящий коммит.Это обычно происходит при выполнении git pull без каких-либо локальных изменений.

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

Аналогично, если вы хотите выполнить git pull или используйте git merge для явной быстрой перемотки вперед, и если вы не можете выполнить быструю перемотку вперед, вы можете выручить, тогда вы можете использовать флаг --ff-only.Таким образом, вы можете регулярно делать что-то вроде git pull --ff-only, не задумываясь, а затем, если произойдет ошибка, вы можете вернуться и решить, хотите ли вы объединить или перебазировать.

877 голосов
/ 14 февраля 2013

Графический ответ на этот вопрос

Вот сайт с четким объяснением и графической иллюстрацией использования git merge --no-ff :

difference between git merge --no-ff and git merge

Пока я не увидел это, я был полностью потерян с мерзавцем.Использование - no-ff позволяет кому-либо, просматривающему историю, четко видеть ветку, которую вы извлекли для работы.(эта ссылка указывает на «сетевой» инструмент визуализации github). И вот еще один замечательный справочник с иллюстрациями.Этот справочник хорошо дополняет первый, с большим акцентом на тех, кто менее знаком с git.


Основная информация для таких новичков, как я

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


Пример рабочего процесса

Я обновил пакет на своем веб-сайте и мне пришлось вернуться назадв мои заметки, чтобы увидеть мой рабочий процесс;Я подумал, что полезно добавить пример к этому ответу.

Мой рабочий процесс команд git:

git checkout -b contact-form
(do your work on "contact-form")
git status
git commit -am  "updated form in contact module"
git checkout master
git merge --no-ff contact-form
git branch -d contact-form
git push origin master

Ниже: фактическое использование, включая пояснения.
Примечание: вывод ниже пропущен;git довольно многословен.

$ git status
# On branch master
# Changed but not updated:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   ecc/Desktop.php
#       modified:   ecc/Mobile.php
#       deleted:    ecc/ecc-config.php
#       modified:   ecc/readme.txt
#       modified:   ecc/test.php
#       deleted:    passthru-adapter.igs
#       deleted:    shop/mickey/index.php
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       ecc/upgrade.php
#       ecc/webgility-config.php
#       ecc/webgility-config.php.bak
#       ecc/webgility-magento.php

Обратите внимание на 3 вещи сверху:
1) В выводе вы можете увидеть изменения в обновлении пакета ECC, включая добавление новых файлов.
2) Также обратите внимание, что есть два файла (не в папке /ecc), которые я удалил независимо от этого изменения.Вместо того, чтобы путать эти удаления файлов с ecc, я сделаю другую ветку cleanup позже, чтобы отразить удаление этих файлов.
3) Я не следил за своим рабочим процессом!Я забыл про мерзавца, когда пытался заставить ecc снова работать.

Ниже: вместо того, чтобы делать все включено git commit -am "updated ecc package" Как обычно, я бы хотел добавить файлы только в папку /ecc.Эти удаленные файлы не были частью моего git add, но, поскольку они уже отслеживались в git, мне нужно удалить их из коммита этой ветки:

$ git checkout -b ecc
$ git add ecc/*
$ git reset HEAD passthru-adapter.igs
$ git reset HEAD shop/mickey/index.php
Unstaged changes after reset:
M       passthru-adapter.igs
M       shop/mickey/index.php

$ git commit -m "Webgility ecc desktop connector files; integrates with Quickbooks"

$ git checkout master
D       passthru-adapter.igs
D       shop/mickey/index.php
Switched to branch 'master'
$ git merge --no-ff ecc
$ git branch -d ecc
Deleted branch ecc (was 98269a2).
$ git push origin master
Counting objects: 22, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (14/14), done.
Writing objects: 100% (14/14), 59.00 KiB, done.
Total 14 (delta 10), reused 0 (delta 0)
To git@github.com:me/mywebsite.git
   8a0d9ec..333eff5  master -> master



Скрипт для автоматизации описанного выше

Воспользовавшись этим процессом более 10 раз в день, я приступил к написанию пакетных сценариев для выполнения команд, поэтому я создал почти правильный git_update.sh <branch> <"commit message"> сценарий дляделать вышеуказанные шаги. Вот источник Gist для этого скрипта.

Вместо git commit -am я выбираю файлы из «модифицированного» списка, созданного с помощью git status, а затем вставляю их в этот скрипт.Это произошло потому, что я сделал десятки правок, но хотел, чтобы различные имена ветвей помогли сгруппировать изменения.

185 голосов
/ 12 февраля 2014

Опция --no-ff гарантирует, что ускоренное слияние не произойдет, и новый объект фиксации всегда будет создан . Это может быть желательно, если вы хотите, чтобы git поддерживал историю ветвей функций. git merge --no-ff vs git merge На изображении выше левая сторона - пример истории мерзавцев после использования git merge --no-ff, а правая сторона - пример использования git merge, где возможно слияние ff.

EDIT : в предыдущей версии этого изображения указывался только один родительский элемент для фиксации слияния. Коммиты слияния имеют несколько родительских коммитов , которые git использует для ведения истории «ветви функций» и исходной ветви. Несколько родительских ссылок выделены зеленым цветом.

103 голосов
/ 04 сентября 2018

Стратегии слияния

Явное слияние : Создает новый коммит слияния. (Это то, что вы получите, если использовали --no-ff.)

enter image description here

Быстрое слияние вперед: Быстрая перемотка вперед без создания нового коммита:

enter image description here

Rebase : установить новый базовый уровень:

enter image description here

Сквош: Раздавить или сжать (что-то) с силой, чтобы она стала плоской:

enter image description here

34 голосов
/ 02 апреля 2014

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

...