Frage Wann verwenden Sie git rebase anstelle von git merge?


Wann wird es empfohlen zu verwenden? git rebase gegen git merge?

Muss ich nach einer erfolgreichen Rebase noch zusammenführen?


1246
2018-04-29 20:26


Ursprung


Antworten:


Kurze Version

  • Zusammenführung nimmt alle Änderungen in einer Verzweigung und führt sie in einer anderen Verzweigung in einer Übergabe zusammen.
  • Rebase sagt, ich möchte den Punkt, an dem ich verzweigt habe, um zu einem neuen Ausgangspunkt zu gelangen

Wann benutzt du dann einen?

Verschmelzen

  • Angenommen, Sie haben einen Zweig erstellt, um ein einzelnes Feature zu entwickeln. Wenn Sie diese Änderungen zurück zum Master bringen möchten, möchten Sie wahrscheinlich verschmelzen (Sie kümmern sich nicht darum, alle vorläufigen Commits beizubehalten).

Rebase

  • Ein zweites Szenario wäre, wenn Sie mit der Entwicklung beginnen und dann ein anderer Entwickler eine Änderung ohne Bezug vornehmen würde. Du willst wahrscheinlich ziehen und dann Rebase um Ihre Änderungen von der aktuellen Version aus dem Repo zu basieren.

973
2018-04-29 20:38



Es ist einfach, mit Rebase sagen Sie, einen anderen Zweig als den neuen zu verwenden Base für deine Arbeit.

Wenn Sie zum Beispiel eine Filiale haben master und Sie erstellen einen Zweig, um ein neues Feature zu implementieren, sagen Sie, dass Sie es benennen cool-featureDer Master-Zweig ist natürlich die Basis für Ihr neues Feature.

Jetzt möchten Sie zu einem bestimmten Zeitpunkt die neue Funktion hinzufügen, die Sie in der master Ast. Du könntest einfach zu wechseln master und füge die cool-feature Ast:

$git checkout master
$git merge cool-feature

Aber auf diese Weise wird eine neue Dummy-Commit hinzugefügt, wenn Sie Spaghetti-Geschichte vermeiden wollen Rebase:

$git checkout cool-feature
$git rebase master

und dann füge es ein master:

$git checkout master
$git merge cool-feature

Dieses Mal, da der Themenzweig die gleichen Commits von Master plus die Commits mit dem neuen Feature hat, wird die Zusammenführung nur ein Schnellvorlauf sein.


288
2018-02-05 06:28



Ergänzen meine eigene Antwort erwähnt von TSamper,

  • Eine Rebase ist oft eine gute Idee vor einer Zusammenführung, weil die Idee ist, dass Sie in Ihre Branche integrieren Y die Arbeit der Branche B auf dem Sie zusammenführen werden.
    Aber noch einmal, bevor Sie sich zusammenschließen, lösen Sie jeden Konflikt in Ihre Verzweigung (d. h. "Rebase", wie in "wiederhole meine Arbeit in meinem Zweig ausgehend von einem kürzlichen Punkt vom Zweig aus B)
    Wenn Sie es richtig gemacht haben, führen Sie die nachfolgende Zusammenführung von Ihrem Zweig zu Ihrem Zweig durch B kann schnell vorwärts sein.

  • Eine Zusammenführung wirkt sich direkt auf den Zielzweig aus B, was bedeutet, dass die Zusammenführungen besser trivial sein müssen, sonst diese Verzweigung B kann lange dauern, um wieder in einen stabilen Zustand zu kommen (Zeit, um alle Konflikte zu lösen)


der Punkt der Verschmelzung nach einer Rebase?

In dem Fall, dass ich beschreibe, rebase ich B auf meinen Zweig, nur um die Gelegenheit zu haben, meine Arbeit von einem neueren Punkt aus wiederzugeben B, aber während ich in meinem Zweig bleibe.
In diesem Fall wird noch eine Zusammenführung benötigt, um meine "replayed" Arbeit zu aktivieren B.

Das andere Szenario (in Git Ready beschrieben zum Beispiel), bringen Sie Ihre Arbeit direkt hinein B durch eine Rebase (die alle Ihre netten Commits bewahrt oder Ihnen sogar die Möglichkeit gibt, sie über eine interaktive Rebase neu zu bestellen).
In diesem Fall (in dem Sie sich in der B-Verzweigung neu festlegen) haben Sie recht: Es ist keine weitere Zusammenführung erforderlich:

Ein Git Baum bei Standard, wenn wir nicht zusammengeführt oder rebased haben

rebase1 

wir bekommen durch Rebasing:

rebase3

In diesem zweiten Szenario geht es darum, wie ich das neue Feature zurück in den Master bekomme.

Mein Punkt, indem ich das erste Rebaseszenario beschreibe, ist es, alle daran zu erinnern, dass eine Rebase auch als ein vorbereitender Schritt dazu verwendet werden kann (das heißt "neues Feature wieder in den Master zu bekommen").
Sie können Rebase verwenden, um den Master zuerst in den Zweig der neuen Funktionen zu bringen: Die Rebase spielt die Commits von neuen Funktionen von der HEAD master, aber immer noch in der Zweigstelle für neue Funktionen, um den Startpunkt Ihrer Verzweigung von einem alten Master-Commit zu verschieben HEAD-master.
Dadurch können Sie Konflikte in beheben Ihre Verzweigung (was isoliert bedeutet, während der Master sich weiter parallel entwickeln kann, wenn die Konfliktlösungsstufe zu lange dauert).
Dann können Sie zu Master und Merge wechseln new-feature (oder Rebase new-feature auf zu master wenn Sie Commits in Ihrem Konto beibehalten möchten new-feature Ast).

Damit:

  • "Rebase vs. Merge" kann als zwei Möglichkeiten angesehen werden, eine Arbeit zu importieren, sagen wir, master.
  • Aber "rebase then merge" kann ein gültiger Workflow sein, um Konflikte zunächst isoliert zu lösen und dann Ihre Arbeit zurückzuholen.

253
2018-04-29 20:44



Viele Antworten hier sagen, dass das Zusammenführen alle Ihre Commits zu einem macht, und schlagen daher vor, Rebase zu verwenden, um Ihre Commits zu bewahren. Das ist falsch. Und eine schlechte Idee, wenn Sie Ihre Commits bereits geschoben haben.

Zusammenführen tut nicht löschen Sie Ihre Commits. Zusammenführung bewahrt Geschichte! (Schau dir einfach gitk an) Rebase schreibt die Geschichte neu, was nach dir eine schlechte Sache ist gedrängt es.

Verwenden Sie Merge - nicht Rebase wann immer du schon gedrängt hast.

Hier ist Linus (Autor von Git) nehmen Sie es an. Es ist eine wirklich gute Lektüre. Oder Sie können meine eigene Version der gleichen Idee unten lesen.

Einen Zweig auf Master neu erstellen:

  • gibt eine falsche Vorstellung davon, wie Commits erstellt wurden
  • verschmutzt den Meister mit einer Reihe von Zwischen-Commits, die möglicherweise nicht gut getestet wurden
  • könnte Build-Breaks für diese zwischenzeitlichen Commits einführen, weil Änderungen vorgenommen wurden, die zwischen der Erstellung des ursprünglichen Zweigzweigs und der Neugenerierung vorgenommen wurden.
  • macht es schwierig, gute Plätze in Master zu finden.
  • Bewirkt, dass die Zeitstempel für Commits nicht mit ihrer chronologischen Reihenfolge im Baum übereinstimmen. Sie würden also sehen, dass Commit A Commit B im Master vorausgeht, aber Commit B wurde zuerst erstellt. (Was?!)
  • Erzeugt mehr Konflikte, da einzelne Commits im Zweig des Themas Merge-Konflikte beinhalten können, die einzeln gelöst werden müssen (Weiter in der Geschichte darüber, was bei jedem Commit passiert ist).
  • ist eine Neuschreibung der Geschichte. Wenn der Zweig, der rebasiert wird, irgendwohin verschoben wurde (mit jemand anderen geteilt), dann hast du alle anderen, die diesen Zweig haben, vermasselt, seit du den Verlauf umgeschrieben hast.

Im Gegensatz dazu, einen Zweig in den Master zusammenführen:

  • bewahrt den Verlauf der Zweige, in denen Zweige erstellt wurden, einschließlich aller Zusammenführungen vom Master zum Zweig, um sie aktuell zu halten. Sie erhalten eine genaue Vorstellung davon, mit welchem ​​Code der Entwickler beim Erstellen gearbeitet hat.
  • Master ist ein Zweig, der hauptsächlich aus Merges besteht, und jedes dieser Merge-Commits ist in der Regel ein "guter Punkt" in der Geschichte, der sicher ausgecheckt werden kann, da dort der Zweig des Themas bereit war, integriert zu werden.
  • Alle einzelnen Commits des Zweigthemas bleiben erhalten, einschließlich der Tatsache, dass sie sich in einem Zweig des Themas befanden. Daher ist es eine Selbstverständlichkeit, diese Änderungen zu isolieren, und Sie können dort bohren, wo es erforderlich ist.
  • Zusammenfügungskonflikte müssen nur einmal (zum Zeitpunkt der Zusammenführung) gelöst werden, so dass temporäre Festschreibungsänderungen, die im Zweig des Themas vorgenommen wurden, nicht unabhängig voneinander gelöst werden müssen.
  • kann mehrmals reibungslos durchgeführt werden. Wenn Sie Ihren Themenzweig regelmäßig in den Master integrieren, können die Leute den Themenzweig weiter aufbauen, und er kann weiterhin unabhängig zusammengeführt werden.

151
2018-02-03 22:17



TL; DR

Wenn Sie irgendwelche Zweifel haben, verwenden Sie Merge.

Kurze Antwort

Die einzigen Unterschiede zwischen einem Rebase und einem Merge sind:

  • Die resultierende Baumstruktur der Historie (im Allgemeinen nur bemerkbar, wenn man sich ein Commit-Diagramm anschaut) ist unterschiedlich (die eine wird Zweige haben, die andere nicht).
  • Die Zusammenführung erzeugt im Allgemeinen eine zusätzliche Festschreibung (z. B. Knoten in der Baumstruktur).
  • Zusammenführen und Umbenennen wird Konflikte anders behandeln. Rebase zeigt Konflikte, die zu einem Zeitpunkt festgeschrieben werden, an dem die Zusammenführung sie alle gleichzeitig darstellt.

Also die kurze Antwort ist zu Wählen Sie Rebase oder Zusammenführen basierend auf dem, wie Ihr Verlauf aussehen soll.

Lange Antwort

Es gibt einige Faktoren, die Sie bei der Auswahl der zu verwendenden Operation beachten sollten.

Wird der Zweig, den Sie erhalten, von anderen Entwicklern außerhalb Ihres Teams (z. B. Open Source, öffentlich) geändert?

Wenn ja, nicht umbasen. Rebase zerstört den Zweig und diese Entwickler haben defekte / inkonsistente Repositories, wenn sie nicht verwendet werden git pull --rebase. Dies ist eine gute Möglichkeit, andere Entwickler schnell zu verärgern.

Wie qualifiziert ist Ihr Entwicklungsteam?

Rebase ist eine destruktive Operation. Das heißt, wenn Sie es nicht richtig anwenden, Sie könnten engagierte Arbeit verlieren und / oder die Konsistenz anderer Entwickler-Repositories brechen.

Ich habe in Teams gearbeitet, in denen die Entwickler alle aus einer Zeit stammten, als sich Firmen engagierte Mitarbeiter leisten konnten, die sich mit Verzweigungen und Fusionen befassen. Diese Entwickler wissen nicht viel über Git und wollen nicht viel wissen. In diesen Teams würde ich nicht riskieren, aus irgendeinem Grund eine Umbasierung zu empfehlen.

Ist der Zweig selbst eine nützliche Information?

Einige Teams verwenden das Zweig-pro-Feature-Modell, bei dem jeder Zweig ein Feature (oder Bugfix oder Untermerkmal usw.) darstellt. In diesem Modell hilft der Zweig dabei, Gruppen von zugehörigen Commits zu identifizieren. Zum Beispiel kann man eine Funktion schnell rückgängig machen, indem man die Zusammenführung dieser Verzweigung rückgängig macht (um fair zu sein, ist dies eine seltene Operation). Oder diff ein Merkmal durch den Vergleich zweier Zweige (häufiger). Rebase würde den Zweig zerstören und das wäre nicht einfach.

Ich habe auch an Teams gearbeitet, die das Zweig-pro-Entwickler-Modell verwendet haben (wir waren alle dort). In diesem Fall liefert die Verzweigung selbst keine zusätzlichen Informationen (das Commit hat bereits den Autor). Es würde nicht schaden, Rebasing zu betreiben.

Möchten Sie die Zusammenführung aus irgendeinem Grund wiederherstellen?

Das Zurücksetzen (wie das Rückgängigmachen) eines Rebases ist erheblich schwieriger und / oder unmöglich (wenn das Rebase Konflikte aufwies) im Vergleich zum Zurücksetzen eines Merges. Wenn du denkst, dass es eine Chance gibt, die du wiederherstellen willst, dann benutze Merge.

Arbeitest du in einem Team? Wenn ja, sind Sie bereit, in dieser Branche einen Alles-oder-nichts-Ansatz zu verfolgen?

Rebase-Operationen müssen mit einem entsprechenden Befehl ausgeführt werden git pull --rebase. Wenn Sie alleine arbeiten, können Sie sich erinnern, welche Sie zur richtigen Zeit verwenden sollten. Wenn Sie an einem Team arbeiten, wird dies sehr schwierig zu koordinieren sein. Aus diesem Grund empfehlen die meisten Rebase-Workflows die Verwendung von Rebase für alle Merges (und git pull --rebase für alle zieht).

Verbreitete Mythen

Merge zerstört Geschichte (beschleunigt Commits)

Angenommen, Sie haben folgende Zusammenführung:

    B -- C
   /      \
  A--------D

Einige Leute geben an, dass die Zusammenführung den Commit-Verlauf "zerstört", da Sie, wenn Sie nur das Protokoll des Master-Zweiges (A - D) betrachten würden, die wichtigen Commit-Nachrichten in B und C verpassen würden.

Wenn das wahr wäre, hätten wir es nicht getan Fragen wie diese. Im Grunde werden Sie B und C sehen, es sei denn Sie explizit fragen, sie (mit --first-parent) nicht zu sehen. Dies ist sehr einfach für sich selbst zu versuchen.

Rebase ermöglicht sicherere / einfachere Zusammenführungen

Die beiden Ansätze verschmelzen unterschiedlich, aber es ist nicht klar, dass einer immer besser ist als der andere, und es kann vom Entwickler-Workflow abhängen. Wenn zum Beispiel ein Entwickler dazu neigt, sich regelmäßig zu verpflichten (z. B. vielleicht, dass sie sich zweimal am Tag verpflichten, wenn sie von der Arbeit nach Hause übergehen), könnte es für eine gegebene Verzweigung viele Commits geben. Viele dieser Commits sehen vielleicht gar nicht wie das Endprodukt aus (ich neige dazu, meinen Ansatz ein oder zweimal pro Feature zu refaktorisieren). Wenn jemand anders an einem verwandten Bereich Code arbeitete und sie versuchten, meine Änderungen zu rebasen, könnte es eine ziemlich mühsame Operation sein.

Rebase ist cooler / sexier / professioneller

Wenn du gerne ein Alias ​​nennst rm zu rm -rf um "Zeit zu sparen", dann ist vielleicht Rebase für Sie.

Meine zwei Cent

Ich denke immer, dass ich irgendwann auf ein Szenario stoße, in dem git rebase das großartige Werkzeug ist, das das Problem löst. So wie ich denke, werde ich auf ein Szenario stoßen, in dem git reflog ein großartiges Werkzeug ist, das mein Problem löst. Ich arbeite jetzt seit über fünf Jahren mit git. Es ist nicht passiert.

Unordentliche Geschichten waren nie wirklich ein Problem für mich. Ich lese meine Commit-Geschichte nie wie einen spannenden Roman. Die meiste Zeit brauche ich eine Geschichte Ich werde Git Schuld oder git Halbierung sowieso verwenden. In diesem Fall ist mir der Merge-Commit tatsächlich nützlich, denn wenn der Merge das Problem einführt, ist das für mich bedeutungsvolle Information.

Aktualisierung (4/2017)

Ich fühle mich verpflichtet zu erwähnen, dass ich persönlich die Verwendung von Rebase gemildert habe, obwohl mein allgemeiner Rat immer noch besteht. Ich habe kürzlich sehr viel mit dem interagieren Eckiges 2 Material Projekt. Sie haben Rebase verwendet, um eine sehr saubere Commit-Geschichte zu führen. Dadurch konnte ich sehr leicht sehen, welche Festschreibung einen bestimmten Fehler behoben hat und ob diese Festschreibung in einem Release enthalten war. Es ist ein großartiges Beispiel für die korrekte Verwendung von Rebase.


114
2018-04-13 02:16



Zusammenführen bedeutet: Erstellen Sie ein einzelnes neues Commit, das meine Änderungen in das Ziel zusammenführt.

Rebase bedeutet: Erstelle eine ganz neue Reihe von Commits, indem ich meine aktuellen Commits als Hinweise benutze. Mit anderen Worten, berechnen Sie, wie meine Änderungen aussehen würden, wenn ich angefangen hätte, sie von dem Punkt aus zu machen, auf den ich mich bewege. Nach dem Rebase müssen Sie Ihre Änderungen möglicherweise erneut testen, und während des Rebases haben Sie möglicherweise einige Konflikte.

In Anbetracht dessen, warum würden Sie umbuchen? Nur um die Entwicklungsgeschichte zu verdeutlichen. Nehmen wir an, Sie arbeiten an Feature X und wenn Sie fertig sind, führen Sie Ihre Änderungen zusammen. Das Ziel wird jetzt ein einzelnes Commit haben, das etwas in Richtung "Feature hinzugefügt X" sagen würde. Anstatt nun zu verschmelzen, würde der Zielentwicklungsverlauf, wenn Sie rebasiert und dann zusammengeführt werden, alle einzelnen Commits in einer einzigen logischen Folge enthalten. Dies macht die Überprüfung später viel einfacher. Stellen Sie sich vor, wie schwer es wäre, den Entwicklungsverlauf zu überprüfen, wenn 50 Entwickler ständig verschiedene Funktionen zusammenführen würden.

Das heißt, wenn Sie den Zweig, an dem Sie gerade arbeiten, bereits in den Upstream verschoben haben, sollten Sie nicht neu auffächern, sondern stattdessen zusammenführen. Bei Zweigen, die nicht stromaufwärts geschoben wurden, neu aufbauen, testen und zusammenführen.

Ein anderes Mal, das Sie vielleicht möchten, ist, wenn Sie Commits von Ihrem Zweig loswerden wollen, bevor Sie stromaufwärts drücken. Zum Beispiel: Commits, die zu einem frühen Zeitpunkt einen Debugging-Code einführen, und andere Commits, die diesen Code aufräumen. Der einzige Weg dazu besteht in der Durchführung eines interaktiven Rebases: git rebase -i <branch/commit/tag>

UPDATE: Sie möchten auch Rebase verwenden, wenn Sie Git als Schnittstelle zu einem Versionskontrollsystem verwenden, das keine nichtlineare Historie unterstützt (z. B. Subversion). Bei der Verwendung der git-svn-Bridge ist es sehr wichtig, dass die Änderungen, die Sie in die Subversion zurückführen, eine sequenzielle Liste von Änderungen über den letzten Änderungen in trunk sind. Es gibt nur zwei Möglichkeiten, dies zu tun: (1) Manuelles Erstellen der Änderungen und (2) Verwenden des Rebase-Befehls, der viel schneller ist.

UPDATE2: Eine zusätzliche Möglichkeit, eine Rebase zu erstellen, ist, dass sie eine Art von Zuordnung von Ihrem Entwicklungsstil zu dem Stil ermöglicht, der in dem Repository akzeptiert wird, an das Sie sich binden. Sagen wir, du magst es, dich in kleinen, kleinen Brocken zu engagieren. Sie haben einen Commit, um einen Tippfehler zu beheben, einen Commit, um unbenutzten Code zu entfernen und so weiter. Wenn Sie fertig sind, was Sie tun müssen, haben Sie eine lange Reihe von Commits. Nehmen wir an, das Repository, zu dem Sie sich verpflichten, ermutigt zu großen Commits. Für die Arbeit, die Sie tun, würde man also ein oder zwei Commits erwarten. Wie nimmst du deine Kette von Commits und komprimierst sie zu dem, was erwartet wird? Sie würden eine interaktive Rebase verwenden und Ihre kleinen Commits in weniger große Blöcke zerquetschen. Das gleiche gilt, wenn das Gegenteil erforderlich war - wenn Ihr Stil ein paar große Commits war, aber das Repo verlangte lange Strings von kleinen Commits. Sie würden eine Rebase verwenden, um das auch zu tun. Wenn Sie stattdessen verschmolzen sind, haben Sie Ihren Commit-Stil jetzt auf das Haupt-Repository übertragen. Wenn es viele Entwickler gibt, können Sie sich vorstellen, wie schwer es wäre, nach einiger Zeit einem Verlauf mit mehreren verschiedenen Commit-Stilen zu folgen.

UPDATE3: Does one still need to merge after a successful rebase? Ja, das tust du. Der Grund ist, dass eine Rebase im Wesentlichen eine "Verschiebung" von Commits beinhaltet. Wie ich oben gesagt habe, werden diese Commits berechnet, aber wenn Sie 14 Commits vom Verzweigungspunkt aus hatten, dann werden Sie nach der Annahme, dass mit Ihrer Rebase nichts schief geht, 14 Commits voraus sein (von dem Punkt, auf den Sie rebasieren) Die Rebase ist fertig. Du hattest eine Filiale vor einer Rebase. Sie werden danach einen Zweig gleicher Länge haben. Sie müssen noch zusammenführen, bevor Sie Ihre Änderungen veröffentlichen. Mit anderen Worten, rebase so oft wie Sie möchten (wieder nur, wenn Sie Ihre Änderungen nicht stromaufwärts geschoben haben). Zusammenführen erst nach dem Rebase.


65
2018-02-05 06:47



vor dem Zusammenführen / Umbenennen:

A <- B <- C    [master]
^
 \
  D <- E       [branch]

nach git merge master:

A <- B <- C
^         ^
 \         \
  D <- E <- F

nach git rebase master:

A <- B <- C <- D' <- E'

(A, B, C, D, E und F sind commits)

Dieses Beispiel und viel mehr gut illustrierte Informationen über Git finden Sie hier: http://excess.org/article/2008/07/ogre-git-tutorial/


54
2018-06-07 06:19



Dieser Satz bekommt es:

Im Allgemeinen besteht der Weg, um das Beste aus beiden Welten zu erhalten, darin, lokal zu rebasen   Änderungen, die Sie vorgenommen haben, aber noch nicht geteilt haben, bevor Sie sie einschieben   um deine Geschichte zu bereinigen, aber nie, was du gepusht hast   irgendwo.

Quelle: http://www.git-scm.com/book/de/v2/Git-Branching-Rebasing#Rebase-vs.-Merge


25
2018-01-05 13:50