15 Stimmen

Was ist der empfohlene Workflow bei Verwendung von Liquibase und Git?

Kürzlich haben wir angefangen, Liquibase zu verwenden. Es ist noch nicht aufgetreten, aber wir haben uns vorgestellt, was passieren würde, wenn zwei Entwickler Änderungen in der Änderungsprotokolldatei im gemeinsam genutzten Git-Repository committen.

Wie kann man einen Merge-Konflikt lösen oder vermeiden? Um diese Frage etwas zu erweitern:

Was ist der empfohlene Arbeitsablauf bei der Verwendung von Liquibase in Kombination mit Git?

Beispiel-Szenario:
- Michael ändert eine Spalte in Tabelle 'customer'.
- Jacob ändert eine Spalte in Tabelle 'account'.
Beide Entwickler fügen also ein zur gleichen Änderungsprotokolldatei changelog.xml hinzu.

BEARBEITEN:

Wie in den Kommentaren erwähnt, ist das Szenario tatsächlich nicht so aufregend. Nehmen wir an, Jacob war der letzte, der seinen Code gepusht hat. Er muss also zuerst pullen. Es wird eine Warnung angezeigt, dass Merge-Konflikte gelöst werden müssen. Er löst den Konflikt, indem er beide Teile des Codes behält, sowohl von Michael als auch von ihm. Die Aktualisierung der Datenbank mit Liquibase bereitet keine Probleme.

Fortgeschrittenes Beispiel-Szenario:
-Michael ändert den Namen der Spalte 'name' in der Tabelle 'customer' in 'first_name', committet und pusht.
-Jacob ändert den Namen der Spalte 'name' in der Tabelle 'customer' in 'last_name' und committet.
-Jacob erhält einen Merge-Konflikt, als er Michaels Code pulled.
-Jacob und Michael besprechen den Konflikt und sind sich einig, dass es 'last_name' sein muss, den Jacob committet und pusht.
-Michael holt den gelösten Konflikt und führt ein Liquibase-Update durch. Dabei tritt ein Fehler auf: column "name" does not exist

8voto

Daniel Lyons Punkte 22151

In meinem Unternehmen verhindert die Art und Weise, wie wir Liquibase verwenden, dass diese Situationen auftreten. Grundsätzlich erstellt man eine separate Liquibase-Datei für jede Änderung. Wir benennen die Dateien nach dem JIRA-Ticket, das die Änderung ausgelöst hat, mit einem kurzen beschreibenden Text. Jede dieser Dateien wird in einem Ordner für die Version des Systems abgelegt, für die sie bestimmt sind; wenn das nächste Release 1.22 ist, wird dieser Ordner erstellt, wenn wir mit den Datenbankänderungen beginnen, und wir legen jede Liquibase-Datei zusammen mit einem update.xml-Skript dort ab, das sie nur einschließt. Diese update.xml-Datei ist der einzige Ort, an dem Konflikte wirklich auftreten können, und sie sind trivial zu lösen.

Um das zu veranschaulichen, dies ist der src/main/liquibase Ordner:

install                        
    projectauthor.xml          
    project_obspriorities.xml  
    project_priorities.xml     
    project_udv.xml            
    project.xml                
    roles.xml                  
    scan.xml                   
    (die anderen Tabellen-Definitionen im System befinden sich hier)

 install.xml                 <-- das liest alle Dateien in ./install

 local.properties            <--
 prod.properties             <--  dies sind Datenbankanmeldeinformationen (Buuh, Zischen)  
 staging.properties          <-- 
 test.properties             <--  

 update.xml                  <-- liest jede Versions-/master.xml-Datei    

 v1.16
    2013-06-06_EVL-2240.xml
    2013-07-01_EVL-2286-remove-invalid-name-characters.xml
    2013-07-02_defer-coauthor-projectauthor-unique-constraint.xml
    master.xml
 v1.17
    2013-07-19_EVL-2295.xml
    2013-09-11_EVL-2370_otf-mosaicking.xml
    master.xml
 v1.18
    2014-05-05_EVL-2326-remove-prerequisite-construct.xml
    2014-06-03_EVL-2750_fix-p-band-polarizations.xml
    master.xml

Die install.xml Datei besteht nur aus Dateieinbindungen:

    ...

Die update.xml Datei erzählt dieselbe Geschichte:

Der einzige Aspekt des Arbeitsablaufs, den ich nicht mag, ist, dass die install/*.xml angeblich die Datenbank erstellen sollten, wie sie genau vor der aktuellen Version war, aber wir denken normalerweise nicht daran, das zu tun.

Wie dem auch sei, dieser Ansatz wird Ihnen viel Ärger mit dem Zusammenführen ersparen. Wir verwenden Subversion und haben mit diesem Ansatz keinerlei Schwierigkeiten beim Zusammenführen.

7voto

Nathan Voxland Punkte 14475

Es gibt immer Randfälle, die manuell behandelt werden müssen, aber sie treten normalerweise sehr selten auf. Git handhabt in der Regel das Zusammenführen von Änderungen auf Textebene problemlos, sodass die zusammengeführte Datei beide Änderungssätze enthält, einer nach dem anderen.

Da liquibase Änderungssätze nach ID/Autor/Dateiname verfolgt, spielt es keine Rolle, dass Jacobs Änderungssatz zufällig vor Michaels im endgültigen Änderungssatz landet. Wenn beide Entwickler den endgültigen Änderungssatz ausführen, wird Liquibase nur den Änderungssatz des anderen Entwicklers ausführen, weil dieser als ausgeführt markiert wurde, während der andere nicht markiert wurde. In allen anderen Umgebungen werden beide Änderungssätze ausgeführt.

Ihre fortgeschrittene Fall stößt auf Probleme, weil beide Entwickler Änderungen machen, die sich gegenseitig widersprechen. Sie könnten auch ähnliche Probleme haben, wenn beide Entwickler eine Spalte löschen oder eine neue Spalte mit demselben Namen hinzufügen. Es ist auch nicht immer einfach ein Entwickler gegen einen anderen, manchmal stammen sich widersprechende Änderungssätze aus zwei separaten Feature-Zweigen, die zusammengeführt werden. Es gibt kein physisches Problem mit dem zusammengeführten Änderungssatz selbst, das Problem besteht darin, dass das neue Changelog nicht logisch korrekt ist. Es ist nicht wirklich ein Git-Problem, sondern ein logisches Problem.

In der Praxis tritt dieser Konflikttyp selten auf, da unterschiedliche Entwickler und verschiedene Zweige normalerweise an separaten Bereichen des Codebasiss arbeiten und wenn es Konfliktpotenzial gibt, wird es durch Kommunikation und Planung bewältigt.

Wenn Sie auf einen Konflikt stoßen, gibt es mehrere Möglichkeiten, ihn zu lösen. Normalerweise wird dies (wie in Ihrem Beispiel) durch Löschen von falschen oder doppelten Änderungssätzen oder durch Erstellen eines brandneuen Änderungssatzes, der eine Kombination von beiden ist, behandelt. In jedem Fall müssen Sie mit Datenbanken umgehen, in denen der "falsche" Änderungssatz ausgeführt wurde. Wie man das am besten behandelt, hängt davon ab, wie viele Systeme es ausgeführt haben.

Wenn es sich um einen einzelnen Entwickler handelt, ist es manchmal am einfachsten, einfach liquibase changeLogSync auszuführen, um den neuen Änderungssatz als ausgeführt zu markieren und die Änderung manuell in der Datenbank vorzunehmen. Wenn der schlechte Änderungssatz kürzlich ausgeführt wurde, könnten sie sogar liquibase rollbackCount X ausführen, um ihre schlechte Änderung rückgängig zu machen und dann den Änderungssatz entfernen und dann liquibase update ausführen.

Wenn es mehrere Konflikte und/oder mehrere Systeme gibt, die fehlerhafte Änderungssätze ausgeführt haben, ist der einfachste Ansatz normalerweise die Verwendung von Tags. Sie können den schlechten Änderungssatz entfernen und einen neuen Änderungssatz hinzufügen, der nur ausgeführt wird, wenn der alte Änderungssatz ausgeführt wurde und die Datenbank in den Zustand versetzt, der von späteren Änderungssätzen erwartet wird. In Ihrem Beispiel würde es den Vornamen zurück in den Namen umbenennen, damit der Änderungssatz von Name zu Nachname problemlos funktioniert.

4voto

L. Holanda Punkte 3904

TL;DR: Fügen Sie /pfad/zur/changelogdatei.xml merge=union in die .gitattributes-Datei ein.

Ich habe einige Diskussionen über separate Dateien gesehen. Es gibt zwei Möglichkeiten, separate Dateien in Liquibase zu haben:

  1. Verwenden Sie das includeAll-Tag und fügen Sie ständig neue Dateien in den Ordner ein.
  2. Verwenden Sie das include-Tag für jede separate Datei in der Masterdatei, um die Reihenfolge festzulegen.

Beide Wege werden dennoch Probleme verursachen: (1) includeAll wird einfach Dateien in lexikografischer Reihenfolge der Dateinamen auswählen, was gut funktioniert, wenn das Changelog jedes Mal ausgeführt wird, wenn eine neue Änderung eingereicht wird, aber dies wird fehlschlagen, wenn Sie auf eine brandneue Datei bereitstellen möchten. Es sei denn, Sie haben eine Namensstrategie, um die Reihenfolge festzulegen. Aber auch hier gibt es ein Problem, wenn Michael und Jacob zur gleichen Zeit arbeiten: Sie verwenden wahrscheinlich den gleichen Namen, was zu Konflikten führt. (2) Sowohl Michael als auch Jacob müssen die letzten Zeilen der Masterdatei bearbeiten. Andernfalls: Merge-Konflikt!

Die eigentliche Lösung besteht nicht darin, Ihre Liquibase-Strategie zu ändern. Behalten Sie einfach die gleiche Strategie bei, der Sie bisher gefolgt sind. Die Wurzel des Problems hier ist die Versionskontrolle und der Merge-Mechanismus. Eine Liquibase-Changelog-Datei ist im Wesentlichen ein Verlauf. Stellen Sie sich das als eine Art Versionshinweisdatei vor, in die Entwickler einfach ihre Arbeit zur letzten Zeile der Datei hinzufügen. In diesem Fall ist es egal, ob zwei Entwickler zwei Zeilen am Ende hinzufügen, beide sollten ungeachtet der Reihenfolge gehen. Die Lösung besteht also darin, eine .gitattributes-Datei im Stammverzeichnis Ihres Git-Projekts zu erstellen (sofern Sie noch keine haben) und die folgende Zeile hinzuzufügen:

/pfad/zur/changelogdatei.xml merge=union

Dies ist immer noch nicht fehlertolerant. Um Ihr fortgeschrittenes Beispielszenario anzugehen, fällt mir keine automatische Strategie oder Workflow ein. Die Entwickler sollten kommunizieren, wenn sie dieselbe Tabelle (oder dieselben DB-Objekte) berühren. Dieses Szenario ist nicht nur ein "Datei" -Konflikt, sondern auch ein semantischer Konflikt. Hier kommt ein guter CI ins Spiel. Der Entwickler, der den Code zuletzt committet und merged, erhält den Fehler und muss sich mit demjenigen in Verbindung setzen, der zuerst gewonnen hat.

Beachten Sie, vielleicht unterstützt Ihr Git-Portal keine Merge-Strategie und Sie erhalten immer noch Merge-Konflikte bei Pull-Requests (auch Merge-Anfragen genannt). Aber dennoch, wenn Sie das sehen und versuchen zurückzuführen oder ein Rebase durchzuführen, um Konflikte zu lösen, ist der Konflikt bereits gelöst. Ich weiß, dass GitLab es unterstützt. Ich bin mir nicht sicher bei Github oder BitBucket.

0voto

Douglas Leeder Punkte 50423

Ich kenne Liquidbase nicht, aber ich glaube, der Fehler liegt beim Schritt "Jacob und Michael diskutierten den Konflikt und waren sich einig, dass es 'last_name' sein muss, was Jacob bestätigte und pushte."

Das Änderungsprotokoll muss mit den durchzuführenden (oder bereits durchgeführten) Operationen übereinstimmen. Man kann also keine gepushten Änderungen entfernen.

Daher ist die richtige Lösung name->first_name UND first_name->last_name.

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