it-swarm.com.de

Was ist der Unterschied zwischen "git merge" und "git merge --no-ff"?

Mit gitk log konnte ich keinen Unterschied zwischen den beiden feststellen. Wie kann ich den Unterschied beobachten (mit einem Git-Befehl oder einem Tool)?

828
user1162226

Das --no-ff Flag verhindert, dass git merge einen "Schnellvorlauf" ausführt, wenn es feststellt, dass Ihr aktuelles HEAD ein Vorläufer des Commits ist, das Sie zusammenführen möchten. Ein schneller Vorlauf ist, wenn git, anstatt ein Merge-Commit zu erstellen, den Verzweigungszeiger so bewegt, dass er auf das eingehende Commit zeigt. Dies tritt normalerweise auf, wenn git pull ohne lokale Änderungen ausgeführt wird.

Gelegentlich möchten Sie jedoch verhindern, dass dieses Verhalten auftritt, in der Regel, weil Sie eine bestimmte Verzweigungstopologie beibehalten möchten (z. B. wenn Sie in einer Zweigstelle zusammenführen und sicherstellen möchten, dass dies beim Lesen des Verlaufs auch so aussieht). Zu diesem Zweck können Sie das --no-ff -Flag übergeben und git merge erstellt immer eine Zusammenführung anstelle einer schnellen Weiterleitung.

Wenn Sie einen git pull ausführen oder git merge verwenden möchten, um einen expliziten Schnellvorlauf durchzuführen, und Sie aussteigen möchten, wenn der Schnellvorlauf nicht möglich ist, können Sie den --ff-only flag. Auf diese Weise können Sie regelmäßig etwas wie git pull --ff-only tun, ohne darüber nachzudenken, und dann, wenn es fehlschlägt, können Sie zurückgehen und entscheiden, ob Sie zusammenführen oder neu zusammenfassen möchten.

935
Lily Ballard

Grafische Antwort auf diese Frage

Hier ist eine Seite mit einer klaren Erklärung und grafischen Darstellung der Verwendung git merge --no-ff:

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

Bis ich das sah, war ich völlig mit Schwachkopf verloren. Verwenden --no-ff Ermöglicht jemandem, der den Verlauf überprüft, deutlich zu sehen, an welchem ​​Zweig Sie gearbeitet haben. (Dieser Link verweist auf das "Netzwerk" -Visualisierungstool von Github.) Und hier ist eine weitere großartige Referenz mit Abbildungen. Diese Referenz ergänzt die erste mit mehr Fokus auf diejenigen, die mit Git weniger vertraut sind.


Grundlegende Informationen für Anfänger wie mich

Wenn Sie wie ich und kein Git-Guru sind, beschreibt meine Antwort hier das Löschen von Dateien aus der Git-Verfolgung, ohne sie aus dem lokalen Dateisystem zu löschen, was schlecht, aber häufig dokumentiert zu sein scheint Auftreten. Eine andere neue Situation ist, den aktuellen Code zu bekommen, der mir immer noch aus dem Weg geht.


Beispiel Workflow

Ich habe ein Paket auf meiner Website aktualisiert und musste zu meinen Notizen zurückkehren, um meinen Workflow zu sehen. Ich fand es nützlich, ein Beispiel zu dieser Antwort hinzuzufügen.

Mein Workflow von Git-Befehlen:

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

Unten: tatsächliche Verwendung, einschließlich Erläuterungen.
Hinweis: Die Ausgabe unten wird abgeschnitten. Git ist ziemlich ausführlich.

$ 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

Beachten Sie 3 Dinge von oben:
1) In der Ausgabe sehen Sie die Änderungen seit dem Upgrade des ECC-Pakets, einschließlich des Hinzufügens neuer Dateien.
2) Beachten Sie auch, dass es zwei Dateien gibt (nicht im Ordner /ecc), die ich unabhängig von dieser Änderung gelöscht habe. Anstatt diese Dateilöschungen mit ecc zu verwechseln, werde ich später eine andere cleanup Verzweigung durchführen, um die Löschung dieser Dateien wiederzugeben.
3) Ich habe meinen Workflow nicht befolgt! Ich habe git vergessen, als ich versuchte, ecc wieder zum Laufen zu bringen.

Unten: Anstatt das All-inclusive-Verfahren git commit -am "updated ecc package" auszuführen, wollte ich normalerweise nur die Dateien im Ordner /ecc hinzufügen. Diese gelöschten Dateien waren nicht speziell Teil meines git add, aber da sie bereits in Git verfolgt wurden, muss ich sie aus dem Commit dieses Zweigs entfernen:

$ 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 [email protected]:me/mywebsite.git
   8a0d9ec..333eff5  master -> master



Skript zur Automatisierung des oben genannten

Nachdem ich diesen Prozess mehr als 10 Mal am Tag verwendet habe, habe ich Batch-Skripte geschrieben, um die Befehle auszuführen. Daher habe ich ein nahezu korrektes git_update.sh <branch> <"commit message">-Skript erstellt, um die obigen Schritte auszuführen. Hier ist die Gist-Quelle für dieses Skript.

Anstelle von git commit -am wähle ich Dateien aus der mit git status erstellten "geänderten" Liste aus und füge sie dann in dieses Skript ein. Dies ist darauf zurückzuführen, dass ich Dutzende von Änderungen vorgenommen habe, aber unterschiedliche Filialnamen wollte, um die Änderungen zu gruppieren.

897
Chris K

Die Option --no-ff stellt sicher, dass kein schneller Vorlauf ausgeführt wird und dass es wird immer ein neues Festschreibungsobjekt erstellt. Dies kann wünschenswert sein, wenn Sie möchten, dass git einen Verlauf von Feature-Zweigen verwaltet.git merge --no-ff vs git merge In der obigen Abbildung ist die linke Seite ein Beispiel für den Git-Verlauf nach der Verwendung von git merge --no-ff und die rechte Seite ist ein Beispiel für die Verwendung von git merge, bei dem ein Zusammenführen möglich war.

EDIT: In einer früheren Version dieses Bildes wurde nur ein einziges übergeordnetes Element für das Zusammenführungs-Commit angegeben. Merge-Commits haben mehrere übergeordnete Commits welche GIT verwendet, um einen Verlauf des "Feature-Zweigs" und des ursprünglichen Zweigs zu pflegen. Die mehrfachen übergeordneten Links werden grün hervorgehoben.

191
Daniel Smith

Strategien zusammenführen

Explizite Zusammenführung : Erstellt ein neues Zusammenführungs-Commit. (Dies erhalten Sie, wenn Sie --no-ff verwendet haben.)

enter image description here

Schnellvorlauf-Zusammenführung: Schnellvorlauf, ohne ein neues Commit zu erstellen:

enter image description here

Rebase : Erstelle ein neues Basislevel:

enter image description here

Squash: Crush oder Squeeze (etwas) mit Kraft, so dass es flach wird:

enter image description here

127
Premraj

Dies ist eine alte Frage, und dies wird in den anderen Posts etwas subtil erwähnt, aber die Erklärung, die diesen Klick für mich verursacht hat, ist folgende: Zusammenführungen ohne schnellen Vorlauf erfordern ein separates Commit.

34
Parris Varney

Das Flag --no-ff bewirkt, dass beim Zusammenführen immer ein neues Festschreibungsobjekt erstellt wird, selbst wenn das Zusammenführen mit einem schnellen Vorlauf durchgeführt werden könnte. Dadurch wird vermieden, dass Informationen über die historische Existenz eines Feature-Zweigs verloren gehen und alle Commits, die das Feature zusammengefügt haben, zusammengefasst werden

1
jsina