Ergebnis 1 bis 7 von 7

[Git] versehentliches mergen verhindern?

  1. #1 Zitieren
    Tieftöner Avatar von Lookbehind
    Registriert seit
    Dec 2007
    Beiträge
    15.176
    Hallo zusammen,

    ich habe mehrere Projekte, die sich eine Code-Basis teilen, die dann auch in allen Projekten gleich sein darf. Andere Teile der Projekte müssen aber unbedingt isoliert bleiben. Sollen aber trotzdem versioniert werden.

    Meine Idee ist nun folgende: Jedes Projekt bekommt einen eigenen Branch in Git. Im Master liegt der gemeinsame Code, und die projektspezifischen Sachen landen in den einzelnen Projekt-Branches.
    Jetzt kann es aber passieren, dass ich bei der Arbeit an einem Projekt die gemeinsame Code-Basis ebenfalls erweitere. Diese Erweiterungen sollen dann auch in den Master-Branch und von da in die anderen Branches gemerged werden. Allerdings NUR diese. Die Projektspezifischen Code-Teile dürfen auf keinen Fall gemerged werden.

    Heißt, ich bräuchte eine Whitelist an Dateien die gemerged werden dürfen, und irgendeine Automatik müsste das bei allen anderen Dateien zuverlässig verhindern.
    Mir ist bekannt, dass ich die zu mergenden Dateien von Hand auswählen kann. Das muss ich dann aber auch jedes mal tun. Und ich kenn mich. Eines Tages ist aus Versehen da mal eine dabei, die nicht gemerged werden darf. Da die teilweise recht sensible Daten enthalten, wäre das absolut fatal!

    Frage: Gibts da was von Ratiopharm? Oder müsste ich mir sowas selbst zusammenscripten?

    Gruß

    Look
    Lookbehind ist offline

  2. #2 Zitieren
    Knight Commander Avatar von Kellendil
    Registriert seit
    Jul 2009
    Beiträge
    2.093
    Unterschiedliche Projekte durch unterschiedliche Branches abzubilden widerspricht jeglichen Workflows & Tools im Git-Bereich, und das aus gutem Grund, denn es ergibt absolut keinen Sinn.

    Warum sollte denn gemeinsamer Code jemals von einem Branch zum anderen dupliziert werden müssen (was du als "mergen" bezeichnest, aber kein mergen ist)? Oder anders gesagt, warum willst du den Code einmal pro Projekt speichern anstatt einmal ingesamt?

    Du machst pro Projekt ein Repo, und für geteilte Ressourcen ebenfalls ein eigenes Repo, fertig ist der Lack. Und dann richtest du deine Build-Technologie so ein, dass das geteilte Repo beim Build eines Projektes aus einem anderen Repo genutzt werden kann.

    Workflow anhand eines Java/Gradle Beispiels:

    - CoreLib ist eigenständiges Gradle Projekt in eigenständigem Git-Repo
    - Application1 ebenfalls, und benötigt CoreLib zum funktionieren
    - CoreLib Repo ist entweder submodule von Application1 Repo oder muss manuell lokal auf einem relativen Pfad bereit gestellt werden. Vorteil submodule: Es wird automatisch sichergstellt, dass die richtige Version von CoreLib Repo für jede Version von Application1 Repo definiert ist (submodule-Abhängigkeiten sind auf Commit festgenagelt).
    - Sowohl CoreLib als auch Application1 können weiterentwickelt werden und können separat comittet werden.
    - Im Application1 Gradle build script trägst du als Abhängigkeit CoreLib ein.


    Edit:
    Wenn mehrer Repos Overkill sind, dann machst du einfach pro Projekt einen ProjektOrdner innerhalb eines einzigen Repos, fertig. Aber um Himmels Willen bitte nicht Branches missbrauchen für etwas, wofür sie absolut ungeeignet sind. Branches sind lediglich Commits mit einem Namen und für parrallele Entwicklung / Versionierung zu nutzen.
    Kellendil ist offline Geändert von Kellendil (23.12.2017 um 10:51 Uhr)

  3. #3 Zitieren
    Tieftöner Avatar von Lookbehind
    Registriert seit
    Dec 2007
    Beiträge
    15.176
    Die kurze Antwort ist also: Nein.
    Gut, danke dafür.

    Zur Erklärung: Die Idee mit einem separaten Repo, welches ich dann nur einbinde, hatte ich natürlich auch schon. Konnte sie aber nach kurzer Recherche direkt wieder verwerfen. Das ist hier nicht praktikabel.
    Grund: Es geht nicht um Programm-Code (wenn man mal von ein bisschen templating absieht), sondern um verschiedene Auszeichnungssprachen. Es gibt also keinen Compiler oder Build-Prozess, der verschiedene Repos zu einem Ergebnis zusammenführen könnte. Erschwerend kommt hinzu, dass die Verzeichnis-Struktur für diese Projekte essentiell ist und somit nicht frei wählbar (oder nur sehr bedingt). Was im Ergebnis dazu führt, dass leider Dateien aus dem Shared-Repo und projektspezifische Dateien nebeneinander im gleichen Verzeichnis liegen müssen. Und das verschachtelt über mehrere Verzeichnisebenen hinweg. Trennen über zwei verschiedene Repos wird damit quasi unmöglich.

    Schade, hätte vieles vereinfacht und man hätte sonst Git super auch zum deployen benutzen können.
    Nunja, dann weiter auf dem umständlichen Weg.
    Lookbehind ist offline

  4. #4 Zitieren

    Batmanistrator
    Avatar von Thoronador
    Registriert seit
    Jul 2005
    Ort
    Morrowind, Vvardenfell-Distrikt
    Beiträge
    20.403
    Zitat Zitat von Lookbehind Beitrag anzeigen
    Erschwerend kommt hinzu, dass die Verzeichnis-Struktur für diese Projekte essentiell ist und somit nicht frei wählbar (oder nur sehr bedingt). Was im Ergebnis dazu führt, dass leider Dateien aus dem Shared-Repo und projektspezifische Dateien nebeneinander im gleichen Verzeichnis liegen müssen. Und das verschachtelt über mehrere Verzeichnisebenen hinweg. Trennen über zwei verschiedene Repos wird damit quasi unmöglich.
    Hmm, das ist natürlich sehr ungünstig.
    Aber mal eine etwas verrückte Idee, keine Ahnung ob die Umsetzung praktikabel ist: Vielleicht könnte man die Dateien dennoch in verschiedenen Repositorys bzw. Verzeichnissen halten und dann mittels UnionFS oder aufs in einer logischen Verzeichnisstruktur vereinigen.
    Thoronador ist offline

  5. #5 Zitieren
    Legende Avatar von jabu
    Registriert seit
    Jul 2011
    Beiträge
    7.328
    So langsam scheint sich der Nebel zu lichten:
    Zitat Zitat von Lookbehind Beitrag anzeigen
    [...]
    Zur Erklärung: Die Idee mit einem separaten Repo, welches ich dann nur einbinde, hatte ich natürlich auch schon. Konnte sie aber nach kurzer Recherche direkt wieder verwerfen. Das ist hier nicht praktikabel.
    Grund: Es geht nicht um Programm-Code (wenn man mal von ein bisschen templating absieht), sondern um verschiedene Auszeichnungssprachen. Es gibt also keinen Compiler oder Build-Prozess, der verschiedene Repos zu einem Ergebnis zusammenführen könnte. Erschwerend kommt hinzu, dass die Verzeichnis-Struktur für diese Projekte essentiell ist und somit nicht frei wählbar (oder nur sehr bedingt). Was im Ergebnis dazu führt, dass leider Dateien aus dem Shared-Repo und projektspezifische Dateien nebeneinander im gleichen Verzeichnis liegen müssen. Und das verschachtelt über mehrere Verzeichnisebenen hinweg. Trennen über zwei verschiedene Repos wird damit quasi unmöglich.

    Schade, hätte vieles vereinfacht und man hätte sonst Git super auch zum deployen benutzen können.
    Nunja, dann weiter auf dem umständlichen Weg.
    Ich versuche mal, das nachzuvollziehen. Es dürfte sich demnach um ein Konsistenzproblem handeln, dem ein Zuständigkeitsproblem zugrundeliegt:

    Nur die für das jeweilige Projekt verantwortliche Instanz hat das Wissen, welche Ressource wo liegen muss. Nur sie kann letztendlich gewährleisten, dass Konsistenz zwischen den Dateien, die dort liegen sollen (gemäß Idee, Liste oder Skript) und den tatsächlich vorliegenden Dateien besteht. Wer mit einer IDE und automatischen Build-Tools arbeitet, hat darüber gewisse Garantien, wenn er den Workflow konsequent durchzieht (worauf du vermutlich angespielt hast).

    Du könntest es auch hier tun, wie auch immer du das automatisieren magst (was gewiss unter Zuverlässigkeitsgesichtspunkten nicht unaufwendig wäre, aber es könnte sich lohnen):

    Wenn bisher das Dateisystem selbst, also über die vorhandenen Dateien, zur Abbildung der Abhängigkeiten genügt hat und überdies bisher als am zuverlässigsten gilt (speziell unter deinem Workflow), dann müsste man doch eigentlich in jedes Verzeichnis eine Datei legen können, welche die zunächst noch externe(n) Abhängigkeit(en) referenziert, um anhand der darin gegebenen Informationen (über einen zentralen Prozess, also per Skript automatisiert) den immer selben Kram in dieses Verzeichnis hineinzukopieren.
    Im Grunde ist doch jedes Verzeichnis wie ein Miniprojekt, wobei der Build-Prozess im Zusammenklauben der benötigten Dateien besteht. Und dieses ist auch die Arbeitsweise einer stinknormalen IDE mit Build-Automatisierung.
    Manche hobbymäßigen IDEs speichern auch nicht viel mehr als einfache Dateilisten. Ich würde dann aber wohl zusätzlich zu dem jeweiligen Pfad einen Hash mit abspeichern lassen, um den bei den Aktualisierungen zu gebrauchen. Jede Aktualisierung würde dann einen vielleicht vergessenen Kopiervorgang (Eintrag existiert, Datei fehlt oder ist versehentlich manuell erstellt worden) implizit nachholen (was sorgfältig zu testen wäre).

    Damit könntest du diese gruseligen Abhängigkeiten aus dem Spiel lassen, was besser für Sicherheit, Wartbarkeit und Zuverlässigkeit wäre. Ich weiß natürlich nicht, ob das von der Systematik her bereits deinen Anforderungen genügt.
    jabu ist offline

  6. #6 Zitieren
    Tieftöner Avatar von Lookbehind
    Registriert seit
    Dec 2007
    Beiträge
    15.176
    Also, um das nochmal klar zu stellen:
    Es gibt keine IDE. Und es gibt auch keinen Build-Prozess.

    Ja, man kann natürlich ein Script (oder was auch immer) schreiben, was einem die Dateien aus zwei verschiedenen Repos zusammenstellt. Das ist aber nicht Ziel der Sache und macht den gesamten Prozess nochmal bedeutend umständlicher, als er ohnehin schon ist.

    Du hast schon recht. Ich versuche die Konsistenz zu vereinfachen. Und es gibt gewissermaßen auch ein Zuständigkeitsproblem. Oder eher ein Berechtigungsproblem. Oder Geheimnisproblem.

    Bisher handhabe ich das wie folgt:
    Ich habe ein zentrales Git-Repo, in dem der shared-Teil liegt. Von da aus clone ich für jedes Projekt in ein neues Projekt-Verzeichnis. In diesem Projekt-Verzeichnis erstelle ich dann einen neuen Branch für genau dieses Projekt. Der Master-Branch bleibt auf dem Stand des Shared-Repos. In dem Projekt-Branch werden dann die projektspezifischen Änderungen und Erweiterungen durchgeführt.
    Oft stellt sich dann hinterher heraus, dass einige Teile dieser Änderungen auch problemlos in das Shared-Repo übernommen werden können.
    Bisher mach ich dass dann mit einem komplett manuellen Merge. Heißt ich schaue in das Changelog vom Projekt-Branch im Projekt-Repo, suche mir dort alle relevanten Änderungen heraus, die in das Shared-Repo übernommen werden sollen, kopiere die Änderungen (also bisweilen wirklich einzelne Code-Zeilen) manuell in die dazugehörigen Dateien des Shared-Repos. Comitte das Shared-Repo. Wechsel in den Projekt-Repos auf den Master-Branch, pulle vom Shared-Repo und merge das dann in den Projekt-Branch.
    Bis hier klingt das aufwändiger und umständlicher, als es in der Praxis ist. Das liegt aber daran, dass das Shared-Repo derzeit noch recht übersichtlich ist, und es bisher erst 3 Sub-Projekte gibt. Es ist aber ab zu sehen, dass sich diese Sache noch über einige Jahre hin ziehen wird, und da noch ein ganzer Haufen weiterer Sub-Projekte hinzukommen wird. Das Potential, dass das irgendwann mal ungemütlich wird, sehe ich jetzt schon. Dem möchte ich gerne vorbeugen.

    Erschwerend kommt noch hinzu, dass das Shared-Repo für sich genommen zu absolut nichts zu gebrauchen ist. Es lässt sich nichtmal testen, ob der Inhalt überhaupt valide ist. Um also weiter entwickeln zu können, muss das zwangsweise immer in ein Projekt mit eingebunden sein. Und wenn es nur ein Test-Projekt ist. Wobei manche Erweiterungen tatsächlich nur am echten Projekt getestet werden können.

    Und jetzt kommt der Punkt, warum ich das an sich gerne in Git selbst gelöst haben wollte, statt da ein extra Zusatztool für zu schreiben. Gebraucht werden die Dateien auf Remote-Systemen. Und zwar pro Projekt ein eignes. Und die dortigen Admins dürfen bisweilen nichtmal wissen, welche anderen Projekte es noch gibt. Die Idee wäre, für jeden ein eigenes, nur für ihn verfügbares Git-Repo zu haben, mit nur dem einen Branch, der zu dem Projekt gehört. Von da können die dann pullen und so ihre Updates holen. (Daher wäre es auch gut, wenn die nur EIN Repo pullen müssten, nicht mehrere.) Die müssen aber dennoch in der Lage sein, eine Änderungshistorie zu verfolgen.

    Gleichzeitig wäre es gut, wenn man für die Entwicklung alles an einem zentralen Ort hat, gegebenenfalls einzelne Branches zur Weiterentwicklung an dritte geben kann, und den Code dennoch wieder in den eigenen Pool integrieren kann. Und das alles schön versioniert, damit man später immer nachvollziehen kann, wann wer welche Änderung gemacht hat, und warum.

    Prinzipiell kann Git das auch alles. Nur eine Sache kann es dabei nicht: Verhindern, dass aus Versehen Dateien in das Shared-Repo zurück gemerget werden, die auf keinen Fall darin landen dürfen. Das kann man theoretisch verhindern, indem man beim mergen extrem vorsichtig ist, und darauf achtet, was man da genau merget. Solange man das tut, ist auch alles super und das Konzept geht auf. Es hat aber blöderweise den Faktor Mensch als einzige Sicherheit, dass da nix schief geht. Ausgerechnet der Faktor Mensch neigt hin und wieder dazu, Fehler zu machen.
    Das würde ich gerne, wenn schon nicht eliminieren (was wohl schwer wird), so zumindest reduzieren.
    Daher die Idee, ob es nicht evtl eine White-List für zu mergende Dateien gibt. Die Antwort auf diese Frage habe ich auch schon bekommen: Nein.

    Nunja, jetzt ist eh erst mal Weihnachten.
    Lookbehind ist offline

  7. #7 Zitieren
    Knight Commander Avatar von Kellendil
    Registriert seit
    Jul 2009
    Beiträge
    2.093
    Ok, na das ist ja mal ein ganz und gar nicht klassischer Anwendungsfall. Vlt. hilft das hier:

    1. Access Rights
    Branches sind immer lediglich ein Pointer auf einen bestimmten Commit. Im Branch selbst ist weder die Branch-History noch sonstwas gespeichert, woran man erkennen könnte, zu welchem Branch ein alter Commit mal gehört hat. Der Branch ergibt sich aus dem Commit, auf den der Branch zeigt, und aus der Kette der Commit-Zeiger (jeder Commit zeigt auf seine Vorgänger). D.h.Commits können z.B. auch zu mehreren Branches gehören, und die Zugehörigkeit kann sich jederzeit ändern.

    U.a. auch deshalb ist es nicht möglich bzw. sinnvoll, Access-Rights auf Basis von Branches zu definieren, den Branches sind wie gesagt nicht dafür gedacht, unterschiedliche Orte darzustellen, sondern sind eher Einsprungspunkte in beliebige Stellen im Commit-Graph. Du kannst also niemandem den Zugriff auf bestimmte Branches sperren (ein Git Repo wird immer komplett geclont), außer du kapselst das gesamte Repo vom User ab und schreibst ein Tool, dass das alleinige Interface vom User zum Repo darstellt und nur die vorgesehenen Infors rausholt.

    2. Datentrennung
    Du kannst ein einfaches Tool schreiben, welches den Staging und Commit-Vorgang automatisiert. Das Tool würde erste einmal alle Änderungen stagen und comitten, die in den Shared Branch gehören, und dem Commit einen passenden Prefix geben in der Message. Anschließend das gleiche für die Dateien, die nicht ins Shared gehören, mit einem anderen Prefix. Das würde dir das manuelle Aufteilen sparen. Stage und Commit kannst du ja auch zeilenweise durchführen. Dass das Tool dafür das Wissen benötigt, was Shared ist und was nicht, ist klar, aber wenn es daran scheitert, kannst du die Automatisierung sowieso generell vergessen.

    Vorteil wäre, dass es dann extrem einfach wäre (manuell oder automatisiert) die Änderungen mit dem Shared Commit Prefix auf den Shared Branch zu bekommen.

    Edit: Frohe Weihnachten! : )
    Kellendil ist offline Geändert von Kellendil (24.12.2017 um 00:41 Uhr)

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •