Ein bisschen komplex zu beschreiben, aber ich werde mein Bestes geben. Grundsätzlich verwenden wir den Git-Workflow, dh wir haben folgende Zweige:
Also, nichts wirklich Komplexes hier. Da es sich bei unserer Anwendung jedoch um eine Webanwendung handelt, die mit einer MySQL-Datenbank ausgeführt wird, erfordern neue Funktionen häufig Änderungen am Datenbankschema. Um dies zu automatisieren, verwenden wir dbdeploy, mit dem wir alternative Scripts für eine bestimmte Nummer erstellen können. Z.B. 00001.sql, 00002.sql usw. Beim Zusammenführen mit dem Integrationszweig überprüft dbdeploy, welche Alterskripte eine höhere Anzahl als die zuletzt ausgeführte Version in dieser spezifischen Datenbank haben und führt diese aus.
Nehmen Sie nun Folgendes an. - Die Integration hat Skripte bis 00200.sql verändert. Alle diese werden in der Integrationsdatenbank ausgeführt. - Entwickler John hat einen Feature-Zweig featureX, der erstellt wurde, als die Integration noch 00199.sql als höchstes Alter-Script hatte.
John erstellt 00200.sql wegen einiger erforderlicher Änderungen des Datenbankschemas.
Irgendwann wird John seine Modifikationen wieder in den Integrationszweig einfügen. John wird einen Merge-Konflikt bekommen und wird sehen, dass seine 00200.sql bereits in der Integration existiert. Das heißt, er muss die in Konflikt stehende Datei öffnen, seinen Inhalt extrahieren, diese Datei wieder auf "meine" setzen (den ursprünglichen Zustand wie bei der Integration) und seinen eigenen Inhalt in eine neue Datei einfügen.
Jetzt, da wir mit zehn Entwicklern arbeiten, bekommen wir diese Situation täglich. Und obwohl wir die Gründe dafür verstehen, ist es manchmal sehr umständlich. John benennt sein Skript um, führt ein Merge-Commit zur Integration durch, schiebt die Änderungen an den Upstream, nur um zu sehen, dass jemand anderes bereits 00201.sql erstellt hat, was John dazu zwingt, den Prozess erneut durchzuführen.
Sicherlich müssen mehr Teams den Git-Workflow verwenden und ein Datenbank-Änderungsmanagement-Tool für die Automatisierung von Datenbankschema-Änderungen verwenden.
Kurz gesagt, meine Fragen sind:
Andere Tipps sind natürlich sehr willkommen.
Rails hat das getan, mit genau den Problemen, die Sie beschreiben. Sie änderten sich in das folgende Schema: Die Dateien (Schienen nennt sie Migrationen) sind mit einem utc-Zeitstempel versehen, wann die Datei erstellt wurde, zB
%Vor%(Der zweite Teil des Namens trägt nicht zur Reihenfolge bei).
Rails zeichnet die Zeitstempel aller ausgeführten Migrationen auf. Wenn Sie ihn auffordern, ausstehende Migrationen auszuführen, wählt er alle Migrationsdateien aus, deren Zeitstempel nicht in der Liste der bereits ausgeführten Migrationen enthalten ist, und führt sie in numerischer Reihenfolge aus.
Sie werden keine Zusammenführungskonflikte mehr erhalten, wenn nicht zwei Personen genau zur selben Zeit einen erstellen.
Dateien werden immer noch in der Reihenfolge ausgeführt, in der Sie sie geschrieben haben, aber möglicherweise mit der Arbeit eines anderen verschachtelt. Theoretisch können Sie immer noch Probleme haben - zB entscheidet Entwickler a, eine Tabelle umzubenennen, für die ich eine Spalte hinzugefügt habe. Das ist viel weniger üblich als 2 Entwickler, die beide Änderungen an der Datenbank vornehmen, und Sie hätten Probleme, die Schemaänderungen nicht zu berücksichtigen. Ich habe gerade Code geschrieben, der eine nicht mehr existierende Tabelle abfragt - irgendwann werden Entwickler, die an verwandten Dingen arbeiten miteinander reden!
Einige Vorschläge:
1 - Werfen Sie einen Blick auf Liquibase, jede Version erhält eine Datei, die auf die Änderungen verweist, die passieren müssen, dann können die Änderungsdateien mit einem aussagekräftigen String und nicht mit einer Nummer benannt werden.
2 - haben Sie einen zentralen Ort, um die nächste verfügbare Nummer zu bekommen, dann benutzen die Leute die letzte Nummer.
Ich habe Liquibase in der Vergangenheit ziemlich erfolgreich verwendet, und wir hatten nicht das Problem, das Sie beschreiben.
Wie Frederick Cheung vorgeschlagen , verwenden Sie Zeitstempel statt einer Seriennummer. Das Anwenden von Schemaänderungen in der Reihenfolge des Datumsstempels sollte funktionieren, da Schemaänderungen nur von Änderungen eines früheren Datums abhängen können.
Geben Sie außerdem den Namen des Entwicklers im Namen des alter-Skripts ein. Dies verhindert Mischkonflikte zu 100%.
Ihr Merge-Hook sollte nur nach neu hinzugefügten Alter-Scripts suchen (im zusammengeschlossenen Zweig vorhanden, aber nicht im Upstream-Zweig) und sie in der Reihenfolge des Zeitstempels ausführen.
Ich habe zwei verschiedene Ansätze benutzt, um Ihr Problem in der Vergangenheit zu überwinden.
Das erste ist, ein ORM zu verwenden, das die Schemaaktualisierungen verarbeiten kann.
Der andere Ansatz besteht darin, ein Skript zu erstellen, das das Datenbankschema inkrementell erstellt. Wenn ein Entwickler eine zusätzliche Zeile in einer Tabelle benötigt, sollte er die entsprechende SQL-Anweisung hinzufügen, nachdem die Tabelle erstellt wurde. Ebenso, wenn er eine neue Tabelle benötigt, sollte er die SQL-Anweisung dafür hinzufügen. Dann wird die Verschmelzung zur Frage, ob die Dinge in der richtigen Reihenfolge ablaufen. Dies ist im Grunde der Vorgang der Datenbankaktualisierung in einem ORM. Solch ein Skript muss sehr defensiv codiert werden, und jede Aussage sollte prüfen, ob ihre Vorteile existieren.
Für das dbvc-Befehlszeilentool verwende ich git log
, um die Reihenfolge der Update-Skripte zu bestimmen.
In diesem Fall bestimmt die Reihenfolge der Commits die Reihenfolge, in der die Updates ausgeführt werden. Welches ist am wahrscheinlichsten, was Sie wollen.
git merge b
ausführen, werden die Aktualisierungen von Master zuerst und dann von B. git rebase b
ausführen, wird das Update von B zuerst und dann von Master ausgeführt.