В чем разница между "git merge" и "git merge --no-ff"?

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

5 ответов


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

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

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


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

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

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

пока я не увидел это, я был полностью потерян с git. Используя --no-ff позволяет кому-то просматривать историю четко смотрите филиал, который вы проверили для работы. (эта ссылка указывает на инструмент визуализации "сеть" github) и здесь is еще одна отличная ссылка с иллюстрациями. Эта ссылка прекрасно дополняет первую, уделяя больше внимания тем, кто менее знаком с 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, Я сделаю другой cleanup филиала поздно, чтобы отразить удаление этих файлов.
3) я не следил за моей работы! Я забыл о git, пока я пытался заставить ecc работать снова.

ниже: вместо того, чтобы делать все включено git commit -am "updated ecc package" Я обычно хотел бы, я только хотел добавить файлы в . Эти удаленные файлы не были специально частью my 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"> скрипт для выполнения вышеуказанных шагов. вот суть источника для этого сценария.

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


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

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


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


Объединить Стратегии

  • явное, не быстрое слияние
  • неявное через rebase или fast-forward merge
  • сквош на слияния

enter image description here

enter image description here

enter image description here

enter image description here