Mit Git merge können wir die Zusammenführung von Zweigen im Schnelldurchlauf und ohne Schnelldurchlauf durchführen. Irgendwelche Ideen, wann man Fast-Forward-Merge und wann No-Fast-Forward-Merge verwenden sollte?
Antworten
Zu viele Anzeigen?En --no-ff
ist nützlich, wenn Sie eine klare Vorstellung von Ihrem Feature-Zweig haben wollen. Selbst wenn in der Zwischenzeit keine Commits gemacht wurden - FF ist möglich - wollen Sie manchmal immer noch, dass jeder Commit in der Mainline einem Feature entspricht. Also behandeln Sie einen Feature-Zweig mit einer Reihe von Commits als eine Einheit, und führen sie als eine Einheit zusammen. Es ist aus Ihrer Geschichte ersichtlich, wenn Sie Feature-Branch-Merging mit --no-ff
.
Wenn Ihnen so etwas egal ist, können Sie wahrscheinlich mit FF auskommen, wann immer es möglich ist. So werden Sie mehr svn-ähnliches Gefühl des Arbeitsablaufs haben.
Der Autor dieses Artikels zum Beispiel Artikel meint, dass --no-ff
Option standardmäßig sein sollte, und seine Argumentation ist ähnlich wie die, die ich oben dargelegt habe:
Stellen Sie sich die Situation vor, dass eine Reihe kleinerer Übertragungen im "Feature"-Zweig zusammen ein neues Feature ergeben: Wenn Sie einfach "git merge feature_branch" ausführen, ohne --no-ff
Es ist unmöglich, in der Git-Historie zu sehen, welche der Commit-Objekte zusammen ein Feature implementiert haben - man müsste alle Protokollmeldungen manuell lesen. Ein ganzes Feature (d.h. eine Gruppe von Commits) rückgängig zu machen, ist ein wahres Kopfzerbrechen [wenn --no-ff
nicht verwendet wird], während es leicht möglich ist, wenn die --no-ff
Flagge verwendet wurde [weil es sich nur um eine Übergabe handelt]."
Ich kann ein Beispiel nennen, das häufig in Projekten vorkommt.
Hier, Option --no-ff
(d.h. echte Zusammenführung ) erstellt eine neue Übergabe mit mehreren Eltern und ermöglicht eine bessere Verfolgung des Verlaufs. Andernfalls, --ff
(d.h. Vorwärtsverflechtung ) ist standardmäßig.
$ git checkout master
$ git checkout -b newFeature
$ ...
$ git commit -m 'work from day 1'
$ ...
$ git commit -m 'work from day 2'
$ ...
$ git commit -m 'finish the feature'
$ git checkout master
$ git merge --no-ff newFeature -m 'add new feature'
$ git log
// something like below
commit 'add new feature' // => commit created at merge with proper message
commit 'finish the feature'
commit 'work from day 2'
commit 'work from day 1'
$ gitk // => see details with graph
$ git checkout -b anotherFeature // => create a new branch (*)
$ ...
$ git commit -m 'work from day 3'
$ ...
$ git commit -m 'work from day 4'
$ ...
$ git commit -m 'finish another feature'
$ git checkout master
$ git merge anotherFeature // --ff is by default, message will be ignored
$ git log
// something like below
commit 'work from day 4'
commit 'work from day 3'
commit 'add new feature'
commit 'finish the feature'
commit ...
$ gitk // => see details with graph
(*) Beachten Sie, dass hier, wenn die newFeature
Zweig wiederverwendet wird, muss git, anstatt einen neuen Zweig zu erstellen, einen --no-ff
trotzdem zusammenführen. Das bedeutet, dass eine schnelle Vorwärtszusammenführung nicht immer möglich ist.
Wenn wir in einer Entwicklungsumgebung arbeiten und unseren Code in den Staging-/Produktionszweig einbringen, kann Git no fast forward eine bessere Option sein. Wenn wir im Entwicklungszweig an einer einzelnen Funktion arbeiten, haben wir in der Regel mehrere Commits. Die Nachverfolgung von Änderungen mit mehreren Commits kann später unpraktisch sein. Wenn wir mit dem Staging-/Produktionszweig mit Git no fast forward zusammenführen, gibt es dort nur 1 Commit. Wenn wir nun die Funktion rückgängig machen wollen, müssen wir nur diesen Commit rückgängig machen. Das Leben ist einfach.
Git-Visualisierung
Hier sind die Git-Log-Visualisierungen mit den Unterschieden. So sahen die Bäume aus, als ich drei Zweige von dev mit der Bezeichnung 1 2 3 erstellte und dann mit und ohne Schnellvorlauf zusammenführte. Ich füge den Einrichtungscode am Ende ein. Sie können einen Absatz mit Befehlen in Ihr Terminal einfügen, um verschiedene Git-Szenarien schnell einzurichten und zurückzusetzen, was beim Lernen von Git sehr hilfreich war.
Beachten Sie, dass Git bei Fast-Forward nicht einmal eine Zusammenführung anzeigt.
--no-ff --ff (default)
* Merge 3
| * 3
* | Merge 2 * Merge 3
| | * 2 | * 3
| |/ * | Merge 2
* / Merge 1 | | * 2
|/ | |/
| * 1 * / 1
|/ |/
* main * main
Es lohnt sich, diesen Ansatz mit der Umbasierung zu vergleichen.
Einrichtung/Abbau
Sie können dies wiederholt ausführen, um das Projektarchiv zu löschen und neu zu initialisieren. Es ist für Windows, also denke ich, Sie müssen nur den Dateipfad und die rd
Verzeichnisbefehle entfernen, wenn Sie unter *nix arbeiten.
Um das Verhalten beim schnellen Vorlauf zu sehen, entfernen Sie --no-ff
aus den Zusammenführungsbefehlen am Ende. Entfernen Sie die --pretty
Stück, wenn Sie die Commit-IDs sehen wollen.
cd \user\docs\code\learning\github\sandbox
rd /s /q 0.git 1 2 3
git init --bare 0.git
git clone 0.git 1
cd 1
git config user.name "user"
git config user.email "user@email.com"
git commit --allow-empty -m main
git switch -c 1 main
git commit --allow-empty -m 1
git switch -c 2 main
git commit --allow-empty -m 2
git switch -c 3 main
git commit --allow-empty -m 3
git switch main
git merge --no-ff 1
git merge --no-ff 2
git merge --no-ff 3
git log --graph --oneline --first-parent --all --pretty=%s
Neben den genannten Gründen für die Verwendung --no-ff
Die Einhaltung einer korrekten übergeordneten Reihenfolge im Zielzweig ist ein weiterer Aspekt.
Verwendung von --no-ff
Die Reihenfolge der Eltern in der letzten Übergabe im resultierenden Zweig ist unabhängig von der Reihenfolge der Eltern in der letzten Übergabe des Zweigs, den Sie zusammenführen, die erste Elternschaft befindet sich im Zielzweig, nicht im Zweig, den Sie zusammengeführt haben. Wenn Sie ein ff durchführen, wird der letzte Commit des Zweiges, den Sie zusammenführen, als letzter in den Zielzweig aufgenommen, so dass der erste Parent des letzten Commits im Zielzweig auf einen Commit außerhalb der Mainline verweist. Das ist wahrscheinlich nicht das, was Sie wollen.
Sie könnten zum Beispiel verwenden --first-parent
einen Zweigverlauf filtern möchten, um nur die wichtigsten Änderungen an einem Zweig zu sehen, oder andere Operationen durchführen möchten, bei denen standardmäßig der erste übergeordnete Zweig verwendet wird, wie revert
. Wenn Ihr Zweig keine korrekte übergeordnete Referenzierung beibehält, würden die Ergebnisse anders ausfallen als erwartet.
- See previous answers
- Weitere Antworten anzeigen