External Sync / How to... / Konflikte beheben / Namensraumkonflikte / Unterschiedliche Elemente mit gleicher UID im selben Namensraum

Unterschiedliche Elemente mit gleicher UID im selben Namensraum (z. B. Inhalte-Verwaltung)

Inhaltsverzeichnis

Dieses Szenario illustriert die Vorgehensweise zur Lösung eines Konflikts, der entsteht, wenn mehrere Entwickler in ihren lokalen Arbeitsversionen des Projekts Elemente unterschiedlichen Typs anlegen, deren UID sich innerhalb desselben Namensraums befinden.

Konkret wird dies anhand eines Beispiels aus der Inhalte-Verwaltung (Page store) durch die simultane Anlage eines Ordners und eines Seitenelements mit derselben UID gezeigt. In diesem Szenario legt ein Entwickler in der Inhalte-Verwaltung einen Ordner, ein anderer Entwickler eine Seite mit identischer UID an, was zu einem UID-Konflikt innerhalb des Namensraums führt, da Seiten und Ordner innerhalb der Inhalte-Verwaltung sich einen Namensraum teilen.

Bei der herkömmlichen Projektentwicklung - mit nur einer Arbeitsinstanz des Projekts - wird normalerweise die FirstSpirit-interne, automatische Auflösung von UID-Konflikten innerhalb eines Namensraums (siehe IDProvider$UidType in der FirstSpirit-Access-API-Dokumentation) angewendet: Soll in der Inhalte-Verwaltung ein Page-Element mit der UID my_new_element angelegt werden, wobei diese UID bereits von einem weiteren Page-Element oder einem Ordner der Inhalte-Verwaltung verwendet wird, so erhält die neue Seite automatisch eine UID mit einem numerischen Suffix, z. B. my_new_element_1).

In der verteilten Entwicklung kann die FirstSpirit-interne UID-Konfliktauflösung nicht angewendet werden, da die Synchronisation der Arbeitsinstanzen des Projekts per Git erfolgt.
Je Arbeitsinstanz kann in der Inhalte-Verwaltung eine Seite oder ein Ordner mit derselben UID angelegt werden. Bei der Synchronisation der Projektdaten zwischen beiden Projektinstanzen muss der hier auftretende UID-Konflikt im Namensraum außerhalb von FirstSpirit aufgelöst werden. Hierbei muss sich der Benutzer entscheiden, welches Element der Inhalte-Verwaltung beibehalten werden soll: dasjenige, das zuerst ins Repository übertragen wurde, oder dasjenige, das lokal erstellt wurde.

Auftreten des Konfliktfalls

Entwickler A

  1. Anlegen eines FirstSpirit-Elements
    Entwickler A legt direkt im Stammordner der Inhalte-Verwaltung einen Ordner mit der UID page_new an.
  2. Export der Änderungen ins Dateisystem
    Entwickler A exportiert per fs-cli den Projektstand ins lokale Dateisystem (Git-Repository)
    fs-cli -p DevProject -sd "D:\Git\DevProject" export pagestore
  3. Überführen der Änderungen ins Git-Repository
    Entwickler A überträgt die Änderungen ins Git-Repository
    git commit -a -m "created page_new"
    git push

Entwickler B

  1. Anlegen eines FirstSpirit-Elements
    Entwickler B legt direkt im Stammordner der Inhalte-Verwaltung eine Seite mit der UID page_new an.
  2. Export der Änderungen ins Dateisystem
    Entwickler B exportiert per fs-cli den Projektstand ins lokale Dateisystem
    fs-cli -p DevProject -sd "D:\Git\DevProject" export pagestore
  3. Überführen der Änderungen ins Git-Repository
    Entwickler B überträgt die Änderungen ins Git-Repository
    git commit -a -m "created page_new"
    git push

Er erhält folgende Log-Meldung:

$ git push
To ssh://firstspirit.example/externalsync
! [rejected] myBranch -> ts/sync-test (non-fast-forward)
error: failed to push some refs to 'ssh://fsgit@ssh://test.domain.com/git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

Diese Meldung warnt Entwickler B, dass im Repository bereits neuere Daten vorhanden sind, als lokal bereitstehen. Das Push kann in diesem Fall erst durchgeführt werden, nachdem die lokale Arbeitsversion per Pull aktualisiert wurde.

Konfliktlösung

Update

Arbeitsverzeichnis gegen das Git-Repository aktualisieren
Entwickler B bringt die lokale Arbeitsversion auf den Stand des Repositorys:
git pull

Beim Versuch, die Arbeitsversion zu aktualisieren, erhält Entwickler B nun folgende Nachrichten:

$ git pull
Auto-merging PageStore/page_new/StoreElement.xml
CONFLICT (add/add): Merge conflict in PageStore/page_new/StoreElement.xml
Auto-merging PageStore/page_new/FS_References.txt
CONFLICT (add/add): Merge conflict in PageStore/page_new/FS_References.txt
Auto-merging PageStore/page_new/FS_Info.txt
CONFLICT (add/add): Merge conflict in PageStore/page_new/FS_Info.txt
Auto-merging PageStore/StoreElement.xml
CONFLICT (add/add): Merge conflict in PageStore/StoreElement.xml
Auto-merging PageStore/FS_References.txt
CONFLICT (add/add): Merge conflict in PageStore/FS_References.txt
Automatic merge failed; fix conflicts and then commit the result.
Finished 'git pull -no-edit' with return code 1

Git-Konflikt auflösen

Die Behandlung dieses Konfliktfalls erfordert manuelle Intervention, da der Git-Client keine Entscheidung treffen kann, welches Element page_new (Seite oder Page Store-Ordner) beibehalten werden soll. Hier müssen die beteiligten Entwickler gemeinsam beschließen, wie der Konflikt zu lösen ist.

An dieser Stelle entscheidet sich Entwickler B nun z. B., den von Entwickler A angelegten Ordner beizubehalten. Dazu führt er über den Git-Client ein Checkout aus, welches im Konfliktfall die im Remote-Repository vorhandenen Dateien übernimmt:

git checkout --theirs *

Die betroffenen Dateien im Verzeichnis PageStore/page_new mit den Änderungen von Entwickler B werden im Konfliktfall also als „zu verwerfen“ betrachtet und mit den Daten aus dem Remote-Repository überschrieben.

Import

Importieren aus dem Dateisystem
Nachdem der Konflikt auf Dateisystem-Ebene (Git) gelöst ist, muss derEntwickler B im nächsten Schritt den Stand aus dem Dateisystem nach FirstSpirit importieren.
fs-cli -p DevProject -sd "D:\Git\DevProject" import

Beim Versuch, die im lokalen Dateisystem vorhandenen Daten in seine lokale Projektinstanz einzuspielen, erhält Entwickler B allerdings eine Fehlermeldung, z. B.:

$ fs-cli -p DevProject -sd "D:\Git\DevProject" import
30.03.2017 13:16:08.958 [ERROR SimpleResult] Import operation not successful
de.espirit.firstspirit.store.access.nexport.exceptions.SyncOperationException: [ExternalSync -
Import] failed: UID conflict: 'x' (de.espirit.firstspirit.store.access.pagestore.PageImpl),
is used by element of different class
(de.espirit.firstspirit.store.access.pagestore.PageFolderImpl)
at de.espirit.firstspirit.store.access.nexport.operations.ImportOperationImpl.perform(ImportOperationImpl.java:117)
at com.espirit.moddev.cli.commands.ImportCommand.call(ImportCommand.java:112)
at com.espirit.moddev.cli.commands.ImportCommand.call(ImportCommand.java:48)
at com.espirit.moddev.cli.Cli.executeCommand(Cli.java:232)
at com.espirit.moddev.cli.Cli.execute(Cli.java:148)
at com.espirit.moddev.cli.Cli.main(Cli.java:105)
Caused by: de.espirit.firstspirit.store.access.feature.ReferenceMismatchException: UID
conflict: 'x' (de.espirit.firstspirit.store.access.pagestore.PageImpl), is used by element of
different class (de.espirit.firstspirit.store.access.pagestore.PageFolderImpl)
at de.espirit.firstspirit.store.access.feature.FeatureUtil.getElement(FeatureUtil.java:235)
at de.espirit.firstspirit.store.access.nexport.AbstractImportContext.getLocalElement(AbstractImportContext.java:68)
at de.espirit.firstspirit.store.access.nexport.importer.ReferencesImporter.fillIdMap(ReferencesImporter.java:122)
at de.espirit.firstspirit.store.access.nexport.importer.ReferencesImporter.sourceInit(ReferencesImporter.java:84)
at de.espirit.firstspirit.store.access.nexport.ExportUtil.initImportElement(ExportUtil.java:1447)
at de.espirit.firstspirit.store.access.nexport.ExportUtil.initImportElement(ExportUtil.java:1466)
at de.espirit.firstspirit.store.access.nexport.ElementFileSystemSync.refresh(ElementFileSystemSync.java:134)
at de.espirit.firstspirit.store.access.nexport.ElementFileSystemSync.getRootImportElements(ElementFileSystemSync.java:168)
at de.espirit.firstspirit.store.access.nexport.operations.ImportOperationImpl.performImport(ImportOperationImpl.java:134)
at de.espirit.firstspirit.store.access.nexport.operations.ImportOperationImpl.perform(ImportOperationImpl.java:115)
... 5 more

Diese Fehlermeldung entsteht dadurch, dass in der Projektinstanz noch die von Entwickler B angelegte Seite mit der UID page_new vorhanden ist und beim Import nicht durch den im Dateisystem nun vorhandenen Ordner mit der UID page_new überschrieben werden kann.

FirstSpirit-Konflikt lösen

Dieser Fehler muss von Entwickler B manuell im Projekt gelöst werden, indem er die Seite mit der UID page_new manuell löscht. Anschließend kann erneut Importiert werden.

Export

Export der Änderungen ins Dateisystem
Im nächsten Schritt exportiert Entwickler B per fs-cli den Projektstand ins lokale Dateisystem
fs-cli -p DevProject -sd "D:\Git\DevProject" export pagestore

Commit / Push

Änderungen ins Git-Repository überführen
Entwickler B hat den Konflikt aufgelöst und kann nun die Änderungen ins Git-Repository überführen
git commit -a -m "created page_new"
git push

Weiteres Vorgehen

Der Konflikt ist aufgelöst. Weder Entwickler A noch Entwickler B müssen zu diesem Zeitpunkt weitere Schritte vornehmen; der Projektstand auf den FirstSpirit-Servern beider Entwickler entspricht dem des Repositorys.

© 2005 - 2024 Crownpeak Technology GmbH | Alle Rechte vorbehalten. | FirstSpirit 2024.12 | Datenschutz