1043 Stimmen

Git-Arbeitsablauf und Fragen zu rebase vs. merge

Ich verwende Git jetzt seit ein paar Monaten für ein Projekt mit einem anderen Entwickler. Ich habe mehrere Jahre Erfahrung mit SVN Also bringe ich wohl eine Menge Gepäck mit in die Beziehung.

Ich habe gehört, dass Git hervorragend zum Verzweigen und Zusammenführen geeignet ist, aber bisher sehe ich das nicht. Sicher, das Verzweigen ist ganz einfach, aber wenn ich versuche, zusammenzuführen, geht alles zum Teufel. Das bin ich von SVN gewohnt, aber mir scheint, dass ich gerade ein minderwertiges Versionierungssystem gegen ein anderes eingetauscht habe.

Mein Partner sagt mir, dass meine Probleme daher rühren, dass ich willkürlich zusammenführen will, und dass ich in vielen Situationen rebase statt merge verwenden sollte. Hier ist zum Beispiel der Arbeitsablauf, den er festgelegt hat:

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature
git checkout master
git merge my_new_feature

Im Wesentlichen erstellen Sie einen Feature-Zweig, führen IMMER einen Re-Base von Master auf den Zweig durch und führen den Zweig wieder auf Master zusammen. Wichtig dabei ist, dass der Zweig immer lokal bleibt.

Hier ist der Arbeitsablauf, mit dem ich begonnen habe

clone remote repository
create my_new_feature branch on remote repository
git checkout -b --track my_new_feature origin/my_new_feature
..work, commit, push to origin/my_new_feature
git merge master (to get some changes that my partner added)
..work, commit, push to origin/my_new_feature
git merge master
..finish my_new_feature, push to origin/my_new_feature
git checkout master
git merge my_new_feature
delete remote branch
delete local branch

Es gibt zwei wesentliche Unterschiede (denke ich): Ich verwende "merge always" anstelle von "rebasing", und ich schiebe meinen Feature-Branch (und meine Feature-Branch-Commits) in das entfernte Repository.

Der Grund für die Remote-Zweigstelle ist, dass ich meine Arbeit während der Arbeit sichern möchte. Unser Repository wird automatisch gesichert und kann wiederhergestellt werden, wenn etwas schief geht. Bei meinem Laptop ist das nicht der Fall, oder nicht so gründlich. Deshalb hasse ich es, Code auf meinem Laptop zu haben, der nicht irgendwo anders gespiegelt ist.

Meine Begründung für die Zusammenführung anstelle von rebase ist, dass merge eine Standardfunktion und rebase eine erweiterte Funktion zu sein scheint. Mein Gefühl sagt mir, dass es sich bei dem, was ich vorhabe, nicht um ein fortgeschrittenes Setup handelt, so dass Rebase unnötig sein sollte. Ich habe sogar das neue Buch Pragmatic Programming über Git durchgelesen, und dort wird merge ausführlich behandelt und rebase kaum erwähnt.

Wie auch immer, ich folgte meinem Arbeitsablauf auf einem aktuellen Zweig, und als ich versuchte, es zurück zu Master zusammenzuführen, ging alles zum Teufel. Es gab Unmengen von Konflikten mit Dingen, die nicht von Bedeutung sein sollten. Die Konflikte ergaben für mich einfach keinen Sinn. Ich brauchte einen Tag, um alles zu sortieren, und gipfelte schließlich in einem erzwungenen Push auf den entfernten Master, da mein lokaler Master alle Konflikte gelöst hat, aber der entfernte Master immer noch nicht zufrieden war.

Was ist der "richtige" Arbeitsablauf für so etwas? Git soll das Verzweigen und Zusammenführen super-einfach machen, und ich sehe es einfach nicht.

Aktualisierung 2011-04-15

Dies scheint eine sehr beliebte Frage zu sein, also dachte ich, ich bringe meine zweijährige Erfahrung seit meiner ersten Frage auf den neuesten Stand.

Es stellt sich heraus, dass der ursprüngliche Arbeitsablauf richtig ist, zumindest in unserem Fall. Mit anderen Worten: Das ist es, was wir tun, und es funktioniert:

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge my_new_feature

Unser Arbeitsablauf ist ein wenig anders, denn wir neigen dazu, Folgendes zu tun Kürbisfusionen anstelle von rohen Zusammenführungen. ( Anmerkung: T ) Dies ermöglicht es uns, unseren gesamten Feature-Zweig in einen einzigen Commit auf Master zu verwandeln. Dann löschen wir unseren Feature-Zweig. Auf diese Weise können wir unsere Commits auf Master logisch strukturieren, auch wenn sie auf unseren Zweigen ein wenig unordentlich sind. Wir gehen also folgendermaßen vor:

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git checkout master
git merge --squash my_new_feature
git commit -m "added my_new_feature"
git branch -D my_new_feature

Squash Merge Kontroverse - Wie mehrere Kommentatoren bemerkt haben, wird beim Squash Merge die gesamte Historie des Funktionszweigs gelöscht. Wie der Name schon sagt, werden alle Commits zu einem einzigen zusammengeführt. Für kleine Features ist das sinnvoll, da es sie in einem einzigen Paket zusammenfasst. Für größere Features ist es wahrscheinlich keine gute Idee, vor allem wenn die einzelnen Commits bereits atomar sind. Es kommt wirklich auf die persönlichen Vorlieben an.

Github und Bitbucket (andere?) Pull Requests - Falls du dich fragst, wie merge/rebase mit Pull Requests zusammenhängt, empfehle ich, alle oben genannten Schritte zu befolgen, bis du bereit bist, zurück zu Master zu mergen. Anstatt manuell mit Git zusammenzuführen, akzeptieren Sie einfach den PR. Beachten Sie, dass dies kein Squash Merge ist (zumindest nicht standardmäßig), aber Non-Squash, Non-Fast-Forward ist die akzeptierte Merge-Konvention in der Pull Request Community (soweit ich weiß). Genauer gesagt, funktioniert es so:

clone the remote repository
git checkout -b my_new_feature
..work and commit some stuff
git rebase master
..work and commit some stuff
git rebase master
..finish the feature, commit
git rebase master
git push # May need to force push
...submit PR, wait for a review, make any changes requested for the PR
git rebase master
git push # Will probably need to force push (-f), due to previous rebases from master
...accept the PR, most likely also deleting the feature branch in the process
git checkout master
git branch -d my_new_feature
git remote prune origin

Ich habe Git lieben gelernt und möchte nie wieder zu SVN zurückkehren. Wenn Sie Probleme haben, bleiben Sie einfach dabei und irgendwann werden Sie das Licht am Ende des Tunnels sehen.

14voto

Pat Notz Punkte 196406

In Ihrer Situation hat Ihr Partner meiner Meinung nach Recht. Das Schöne an der Umbasierung ist, dass Ihre Änderungen für Außenstehende so aussehen, als wären sie alle in einer sauberen Abfolge erfolgt. Das bedeutet

  • Ihre Änderungen sind sehr einfach zu überprüfen
  • Sie können weiterhin nette, kleine Übertragungen vornehmen und dennoch eine Reihe dieser Übertragungen auf einmal veröffentlichen (indem Sie sie in Master zusammenführen)
  • Wenn Sie sich den öffentlichen Master-Zweig ansehen, werden Sie verschiedene Reihen von Übertragungen für verschiedene Funktionen von verschiedenen Entwicklern sehen, aber sie werden nicht alle miteinander vermischt sein

Sie können weiterhin Ihren privaten Entwicklungszweig zur Sicherung in das entfernte Repository verschieben, aber andere sollten diesen Zweig nicht als "öffentlichen" Zweig behandeln, da Sie ein Re-Basing durchführen werden. Übrigens, ein einfacher Befehl für diese Aufgabe ist git push --mirror origin .

Der Artikel Paketierung von Software mit Git erklärt recht gut die Nachteile des Zusammenführens gegenüber dem Umbasieren. Es ist ein etwas anderer Kontext, aber die Prinzipien sind die gleichen - es kommt im Wesentlichen darauf an, ob Ihre Zweigstellen öffentlich oder privat sind und wie Sie planen, sie in die Hauptlinie zu integrieren.

13voto

CB Bailey Punkte 693084

Jedenfalls folgte ich meinem Arbeitsablauf auf einem aktuellen Zweig, und als ich versuchte, ihn wieder mit Master zusammenzuführen, ging alles den Bach runter. Es gab Unmengen von Konflikten mit Dingen, die eigentlich keine Rolle spielen sollten. Die Konflikte ergaben für mich einfach keinen Sinn. Ich brauchte einen Tag, um alles zu sortieren, und gipfelte schließlich in einem erzwungenen Push auf den entfernten Master, da mein lokaler Master alle Konflikte gelöst hat, aber der entfernte Master immer noch nicht zufrieden war.

Weder in den von Ihrem Partner noch in den von Ihnen vorgeschlagenen Arbeitsabläufen sollten Sie auf Konflikte gestoßen sein, die nicht sinnvoll waren. Selbst wenn dies der Fall wäre, sollte nach der Lösung des Konflikts kein "erzwungener" Push erforderlich sein, wenn Sie sich an die vorgeschlagenen Arbeitsabläufe halten. Es deutet darauf hin, dass Sie den Zweig, zu dem Sie pushen wollten, nicht wirklich zusammengeführt haben, sondern einen Zweig pushen mussten, der nicht von der entfernten Spitze abstammte.

Ich denke, Sie sollten sich genau ansehen, was passiert ist. Könnte jemand anderes (absichtlich oder unabsichtlich) den entfernten Master-Zweig zwischen Ihrer Erstellung des lokalen Zweigs und dem Punkt, an dem Sie versucht haben, ihn wieder in den lokalen Zweig zusammenzuführen, zurückgespult haben?

Im Vergleich zu vielen anderen Versionskontrollsystemen habe ich die Erfahrung gemacht, dass man sich bei der Verwendung von Git weniger mit dem Tool herumschlagen muss und sich auf die Probleme konzentrieren kann, die für den Quellcode grundlegend sind. Git kann zwar nicht zaubern, so dass widersprüchliche Änderungen zu Konflikten führen, aber durch die Verfolgung der Commit-Elternschaft sollte es einfach sein, das Schreiben zu erledigen.

11voto

Rakka Rage Punkte 12771

"Selbst wenn Sie ein einzelner Entwickler mit nur wenigen Zweigen sind, lohnt es sich, sich die korrekte Verwendung von rebase und merge anzugewöhnen. Das grundlegende Arbeitsmuster wird wie folgt aussehen:

  • Erstellen eines neuen Zweigs B aus dem bestehenden Zweig A

  • Änderungen an Zweig B hinzufügen/übertragen

  • Aktualisierungen aus Zweig A wiederherstellen

  • Änderungen aus Zweig B in Zweig A zusammenführen"

https://www.atlassian.com/git/tutorials/merging-vs-rebasing/

8voto

Pepe Punkte 81

Meiner Beobachtung nach neigt git merge dazu, die Zweige auch nach dem Zusammenführen getrennt zu halten, während rebase und merge sie zu einem einzigen Zweig zusammenfassen. Letzteres ist viel sauberer, während es bei ersterem einfacher wäre, herauszufinden, welche Commits zu welchem Zweig gehören, selbst nach dem Zusammenführen.

5voto

Bombe Punkte 77831

Bei Git gibt es keinen "richtigen" Arbeitsablauf. Verwenden Sie das, was Sie am meisten begeistert. Wenn Sie jedoch beim Zusammenführen von Zweigen ständig Konflikte bekommen, sollten Sie Ihre Bemühungen vielleicht besser mit Ihren Entwicklerkollegen koordinieren. Es hört sich so an, als ob Sie beide ständig dieselben Dateien bearbeiten. Achten Sie auch auf Leerzeichen und Subversion-Schlüsselwörter (d.h. "$Id$" und andere).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X