389 Stimmen

Welche Git-Verzweigungsmodelle funktionieren für Sie?

Unser Unternehmen verwendet derzeit ein einfaches Verzweigungsmodell (Stamm/Release/Hotfixes) und würde gerne wissen, welche Verzweigungsmodelle für Ihr Unternehmen oder Ihren Entwicklungsprozess am besten geeignet sind.

  1. Arbeitsabläufe/Verzweigungsmodelle

    Im Folgenden sind die drei wichtigsten Beschreibungen aufgeführt, die ich gesehen habe, aber sie widersprechen sich teilweise oder gehen nicht weit genug, um die nachfolgenden Probleme zu lösen, auf die wir gestoßen sind (wie unten beschrieben). Daher ist unser Team bisher auf nicht so gute Lösungen ausgewichen. Machen Sie etwas Besseres?

  2. Zusammenführung vs. Umbasierung (verworrene vs. sequentielle Geschichte)

    Sollte man pull --rebase oder mit dem Zurückführen auf die Hauptlinie warten, bis Ihre Aufgabe abgeschlossen ist? Ich persönlich neige zum Zusammenführen, da dies eine visuelle Darstellung der Basis, auf der eine Aufgabe begonnen und beendet wurde, bewahrt, und ich bevorzuge sogar merge --no-ff zu diesem Zweck. Es hat jedoch andere Nachteile. Viele haben auch die nützliche Eigenschaft des Zusammenführens nicht erkannt - dass es nicht kommutativ (Das Zusammenführen eines Themenzweigs in den Hauptzweig bedeutet nicht, dass der Hauptzweig in den Themenzweig zusammengeführt wird).

  3. Ich bin auf der Suche nach einem natürlichen Arbeitsablauf

    Manchmal passieren Fehler, weil unsere Verfahren eine bestimmte Situation nicht mit einfachen Regeln erfassen. Zum Beispiel sollte eine Korrektur, die für frühere Versionen benötigt wird, natürlich so weit stromabwärts angesiedelt sein, dass es möglich ist, sie stromaufwärts in alle notwendigen Zweige einzubringen (ist die Verwendung dieser Begriffe klar genug?). Es kommt jedoch vor, dass ein Fix es in den Master schafft, bevor der Entwickler merkt, dass er weiter stromabwärts hätte platziert werden sollen, und wenn dieser bereits gepusht (oder noch schlimmer, zusammengeführt oder etwas darauf basierendes) wurde, dann bleibt nur noch die Möglichkeit des Rosinenpickens, mit den damit verbundenen Gefahren. Welche einfachen Regeln wie diese verwenden Sie? Dazu gehört auch die Unannehmlichkeit, dass ein Themenzweig andere Themenzweige zwangsläufig ausschließt (vorausgesetzt, sie sind von einer gemeinsamen Basislinie abgezweigt). Entwickler wollen nicht ein Feature fertigstellen, um ein anderes zu beginnen, mit dem Gefühl, dass der Code, den sie gerade geschrieben haben, nicht mehr da ist

  4. Wie kann man vermeiden, dass es zu Konflikten bei der Zusammenführung kommt (aufgrund von Cherry-Pick)?

    Es scheint ein sicherer Weg zu sein, einen Merge-Konflikt zu erzeugen, wenn man zwischen Zweigen wählt, die nie wieder zusammengeführt werden können. Würde die Anwendung der gleichen Übergabe in revert (wie geht das?) in beiden Zweigen diese Situation möglicherweise lösen? Dies ist ein Grund, warum ich mich nicht traue, einen weitgehend Merge-basierten Arbeitsablauf zu fordern.

  5. Wie zerfällt man in aktuelle Zweige?

    Uns ist klar, dass es großartig wäre, eine fertige Integration aus Themenzweigen zusammenzustellen, aber oft ist die Arbeit unserer Entwickler nicht klar definiert (manchmal ist es einfach nur ein "Herumstochern") und wenn ein Teil des Codes bereits in ein "Verschiedenes"-Thema gegangen ist, kann er gemäß der obigen Frage nicht wieder aus diesem herausgenommen werden? Wie arbeiten Sie mit dem Definieren/Bewilligen/Graduieren/Freigeben Ihrer Themenzweige?

  6. Angemessene Verfahren wie Code-Review und Graduierung wäre natürlich schön.

    Aber wir können die Dinge einfach nicht genug entwirren, um das zu schaffen - haben Sie Vorschläge? Integrationszweige, Illustrationen?

Nachfolgend finden Sie eine Liste von Fragen zum Thema:

Lesen Sie auch, was Plastic SCM zu folgenden Themen schreibt aufgabenorientierte Entwicklung und wenn Plastik nicht Ihre Wahl ist, studieren Sie nvie's Verzweigungsmodell und seine unterstützende Skripte .

22voto

Ich denke, und ich könnte mich irren, dass eines der Dinge, die an Git am meisten missverstanden werden, seine verteilte Natur ist. Dadurch unterscheidet es sich in der Art und Weise, wie man arbeiten kann, sehr von Subversion, obwohl man das Verhalten von SVN nachahmen kann, wenn man will. Das Problem ist, dass so gut wie jeder Arbeitsablauf funktioniert, was zwar toll, aber auch irreführend ist.

Wenn ich die Kernelentwicklung richtig verstanden habe (ich werde mich darauf konzentrieren), hat jeder sein eigenes Git-Repository für die Entwicklung des Kernels. Es gibt ein Repository, linux-2.6.git, das von Torvalds betreut wird und als Release-Repository dient. Die Leute klonen von hier, wenn sie mit der Entwicklung einer Funktion gegen den "Release"-Zweig beginnen wollen.

Andere Repositories entwickeln etwas. Die Idee ist, von linux-2.6 zu klonen und so oft zu verzweigen, bis man eine funktionierende "neue" Funktion hat. Dann, wenn es fertig ist, können Sie es jemandem zur Verfügung stellen, der als vertrauenswürdig angesehen wird, der diesen Zweig aus Ihrem Repository in sein eigenes zieht und es in den Mainstream einbindet. Beim Linux-Kernel geschieht dies auf mehreren Ebenen (vertrauenswürdige Leutnants), bis er linux-2.6.git erreicht, wo er dann "der Kernel" wird.

Jetzt wird es verwirrend. Die Namen der Verzweigungen müssen in den Repositories nicht konsistent sein. Ich kann also git pull origin master:vanilla-code und erhalten eine Verzweigung aus dem origin in einem Zweig in meinem Repository namens vanilla-code . Solange ich weiß, was vor sich geht, ist es wirklich egal - es ist in dem Sinne verteilt, dass alle Repositories untereinander Peers sind und nicht nur über mehrere Computer verteilt wie SVN.

Mit all diesen Überlegungen:

  1. Ich denke, es ist jedem Programmierer selbst überlassen, wie er seine Verzweigungen gestaltet. Alles, was man braucht, ist ein zentrales Repository für die Verwaltung von Releases usw. Trunk könnte sein head . Releases können Tags oder Zweige sein und Hotfixes sind wahrscheinlich selbst Zweige. In der Tat würde ich wahrscheinlich Releases als Zweige machen, damit man Parcheando sie behalten kann.
  2. Ich würde fusionieren und nicht rebasen. Wenn du zum Beispiel ein Repository nimmst, es klonst, verzweigst und etwas Entwicklung betreibst, dann ziehst du von deinem origin sollten Sie in Ihrem Repository wahrscheinlich einen weiteren Zweig erstellen und die neueste master en yourbranch damit jemand anderes Ihre Änderungen mit möglichst wenig Aufwand übernehmen kann. Meiner Erfahrung nach besteht nur sehr selten die Notwendigkeit, wirklich zu rebasen.
  3. Ich denke, man muss verstehen, wie Git funktioniert und was es kann. Es braucht eine Weile und eine Menge guter Kommunikation - ich habe erst wirklich angefangen zu verstehen, was vor sich geht, als ich anfing, Git mit anderen Entwicklern zu benutzen, und selbst jetzt bin ich mir bei einigen Dingen nicht sicher.
  4. Zusammenführungskonflikte sind nützlich. Ich weiß, ich weiß, Sie wollen, dass alles funktioniert, aber Tatsache ist, dass sich der Code ändert und Sie die Ergebnisse zu etwas zusammenführen müssen, das funktioniert. Zusammenführungskonflikte sind im Grunde nur mehr Programmierung. Ich habe nie eine einfache Erklärung dafür gefunden, was man mit ihnen machen kann, also hier ist sie: Notieren Sie die Dateien, die Merge-Konflikte haben, gehen Sie hin und ändern Sie sie so, wie sie sein sollten, git add . und dann git commit .
  5. Wie auch immer es passt. Wie gesagt, jeder Benutzer hat sein eigenes Git-Repository, mit dem er spielen kann, und Branch-Namen müssen nicht identisch sein . Wenn Sie beispielsweise ein Staging-Repository hätten, könnten Sie ein Namensschema durchsetzen, aber das müssen Sie nicht für jeden Entwickler, sondern nur für das Release-Repository.
  6. Dies ist die Phase des Zusammenführens. Sie fügen nur dann in Versionszweige usw. ein, wenn Sie der Meinung sind, dass der Code überprüft wurde/den Qualitätstest bestanden hat.

Ich hoffe, das hilft. Ich weiß, dass VonC gerade eine sehr ähnliche Erklärung gepostet hat... Ich kann nicht schnell genug tippen!

Modifier einige weitere Überlegungen zur Verwendung von Git in einem kommerziellen Umfeld, da dies nach den Kommentaren für den Auftraggeber relevant zu sein scheint:

  • Das Release-Repository, nennen wir es product.git ist für eine Reihe von leitenden Programmierern/Technikern zugänglich, die sich um das Produkt selbst kümmern. Sie sind vergleichbar mit der Rolle der Maintainer in OSS.
  • Diese Programmierer sind wahrscheinlich auch teilweise federführend bei der Entwicklung neuer Versionen, d. h. sie programmieren möglicherweise auch selbst und pflegen verschiedene Repositories. Sie könnten Staging-Repositories für wirklich neue Funktionen verwalten und sie könnten auch ihre eigenen Repositories haben.
  • Darunter befinden sich Programmierer, die für die Entwicklung einzelner Bits zuständig sind. Zum Beispiel könnte jemand für die Arbeit an der Benutzeroberfläche verantwortlich sein. Er verwaltet daher das Repository UI.git.
  • Unter ihnen befinden sich die eigentlichen Programmierer, die die Funktionen in ihrer täglichen Arbeit entwickeln.

Was passiert also? Nun, jeder zieht zu Beginn eines jeden Tages aus der "Upstream"-Quelle, d.h. dem Release-Repository (das wahrscheinlich auch das neueste Material der Entwicklung des Vortages enthält). Jeder macht das direkt. Dies wird in einem Zweig in ihrem Repository abgelegt, der wahrscheinlich "master" oder, wenn Sie ich sind, vielleicht "latest" heißt. Der Programmierer wird dann etwas Arbeit erledigen. Diese Arbeit könnte etwas sein, bei dem sie sich nicht sicher sind, also erstellen sie einen Zweig und machen die Arbeit. Wenn es nicht funktioniert, kann er den Zweig löschen und zurückgehen. Wenn es klappt, müssen sie den Zweig mit dem Hauptzweig zusammenführen, an dem sie gerade arbeiten. Nehmen wir an, es handelt sich um einen UI-Programmierer, der an latest-ui also tut er git checkout latest-ui gefolgt von git merge abc-ui-mywhizzynewfeature . Er sagt dann zu seinem technischen Leiter (dem UI-Leiter): "Hey, ich habe eine solche Aufgabe erledigt, zieh mich ab. Der UI-Lead macht also git pull user-repo lastest-ui:lastest-ui-suchafeature-abc . Der UI-Verantwortliche sieht sich das dann in diesem Zweig an und sagt: "Das ist wirklich sehr gut, ich werde es in ui-latest . Er könnte dann allen, die unter ihm stehen, sagen, dass sie von ihm abziehen sollen, wenn sie ui-latest Zweige oder wie auch immer sie genannt werden, und so wird die Funktion von den Entwicklern erforscht. Wenn das Team zufrieden ist, kann der UI-Lead den Testing-Lead bitten, die Änderungen von ihm zu übernehmen und sie zusammenzuführen. Dies wird an alle (nach der Änderung) weitergegeben, die sie testen und Fehlerberichte einreichen usw. Wenn die Funktion schließlich die Tests usw. besteht, kann einer der technischen Leiter sie in die aktuelle Arbeitskopie des Programms einfügen, woraufhin alle Änderungen wieder nach unten weitergegeben werden. Und so weiter.

Es handelt sich nicht um eine "traditionelle" Arbeitsweise und ist eher "peer-driven" als "hierarchisch" wie SVN/CVS. Im Wesentlichen hat jeder Zugriff auf Commits, aber nur lokal. Es ist der Zugriff auf das Repository und das Repository, das Sie als Release-Repository bestimmen, das Ihnen die Verwendung der Hierarchie ermöglicht.

10voto

John Nilsson Punkte 16587

Ein Modell, das ich mit guten Ergebnissen verwendet habe, ist das folgende:

Ein "gesegnetes" Repo, in das jeder schiebt und von dem jeder zieht, im Grunde eine Client-Server-Topologie.

Es gibt keinen Master-Zweig, so dass kein Entwickler irgendeinen Code in "mainline" einbringen kann.

Alle Entwicklungen finden in Themenbereichen statt. Wir haben die Namen getrennt, um leicht zu erkennen, wer dafür verantwortlich ist: jn/newFeature oder jn/issue-1234

Außerdem gibt es eine nahezu 1:1-Zuordnung zwischen den Zweigen und den Kanban-/Scrum-Karten auf dem Whiteboard.

Um einen Zweig freizugeben, wird er in das gesegnete Repository gepusht und die Kanban-Karte wird auf "Bereit zur Überprüfung" gesetzt.

Wenn der Zweig dann von der Überprüfung akzeptiert wird, ist er ein Kandidat für eine Veröffentlichung.

Eine Veröffentlichung erfolgt, wenn eine Reihe von akzeptierten Zweigen zusammengeführt und mit einer Versionsnummer versehen wird.

Durch das Einfügen des neuen Tags in das gesegnete Repo entsteht eine neue mögliche Basis für neue Funktionen.

Um Merge-Konflikte zu vermeiden, werden die Entwickler gebeten, ihre unveröffentlichten Zweige auf das neueste Release-Tag zu aktualisieren (zusammenzuführen).

2voto

xero Punkte 3850

Ich persönlich versuche, nur veröffentlichungsfähigen Code im Master-Zweig zu behalten.

Wenn ich an einem neuen Feature oder einer Fehlerbehebung arbeite, mache ich das in einem Zweig. Ich führe auch Unit-Tests in diesem Zweig durch. Wenn alles in Ordnung ist, führe ich den Zweig in den Master-Zweig zurück.

Ich versuche auch, gängige Namenskonventionen für Verzweigungen zu verwenden, z. B:

  • Fehlerbehebung/rekursive_Schleife
  • Fehlerbehebung/sql_timeout
  • merkmal/neues_layout
  • feature/enhanced_search

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