Forum: PC-Programmierung GIT - Mehrere Projekte in einem Verzeichnis


von Timm R. (Firma: privatfrickler.de) (treinisch)


Lesenswert?

Hallo,

die Antwort muss da sein, aber irgendwie bin ich suchtechnisch auf dem 
Holzweg.

Ich benutze zwar git, aber nur sehr rudimentär, als eine Art 
Einzelbenutzer Absicherung gegen zerstörerische oder idiotische 
Änderungen.

Ich würde gern ein Verzeichnis (bzw. dessen Inhalt) aus mehreren 
Repositories zusammensetzen (das sollte kein Problem sein, soweit ich 
sehen kann) und umgekehrt, das ist das Problem, auch wieder in mehrere 
Repositories commiten.

Es geht um eine php-Applikation. An den Dateien der Applikation will 
ich, bis auf eine Ausnahme, nicht herumwerkeln, von daher würde ich 
dieses "Stammsystem" immer nur auschecken. Die Applikation läuft auf 
einer handvoll Systeme, die soweit alle identisch konfiguriert sind, 
dass heißt, die Konfigurationsdateien (.htaccess und config.php) sind 
auf allen Systemen identisch. Vielleicht lässt sich ja Versionierung und 
Verteilung elegant über das git-System regeln?


1. Anliegen
Es gibt eine Konfigurationsdatei, die würde ich gern versionieren. Ein 
commit würde immer in das config-Datei-Repo gehen, das selbe gilt für 
die .htaccess.

2. Anliegen
Aber was wirklich wichtig wäre, wären eben lokale Modifikationen, die 
erfolgen ausschließlich in Dateien, die es im Stammsystem nicht gibt, 
von daher wäre jede Datei im gesamten Verzeichnis, abgesehen von den 
genannten .htaccess und config.php exakt einem Projekt / Repository 
zuzuordnen.


Ich stelle mir das aktuell so vor, wenn ich eine Installation machen 
möchte:

1. "Stammsystem" auschecken
2. Config-Repository auschecken
3. Projekt-Repositories auschecken

Und schon habe ich eine Installation mit dem aktuellen Projektstand.

Jetzt programmiert jemand in der Installation rum, macht

4. commit des betroffenen Projektes

und dann kann man einfach auf einer anderen Installation auch wieder

5. Projekt-Repositories auschecken

Und ist auf dem gewünschten Stand.

Geht das? Wie heißt das Stichwort, nach dem ich googeln muss?

Vielen Dank für jeden Hinweis

Timm

von René H. (Gast)


Lesenswert?


von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

guck Dir mal gits submodules an. Die können echt die Pest sein, aber 
ggf. Dein Problem lösen.

von Timm R. (Firma: privatfrickler.de) (treinisch)


Lesenswert?

Hallo,

wenn ich das richtig gelesen habe, lösen die beiden Vorschläge das 
Problem nicht wirklich elegant.

Ich weiß grad die echten Verzeichnisnamen nicht, aber so sieht es 
ungefähr aus:

web          <- Das Wurzelverzeichnis in dem alle Projekte leben
/web/a/        <- Ein Verzeichnis vom fremden Projekt
/web/b/c/      <- Ein Verzeichnis vom fremden Projekt
/web/b/d/      <- Mein Projekt A
/web/b/e/      <- Mein Projekt B
/web/f/        <- Mein Projekt A
/web/g/        <- Mein Projekt B

Natürlich noch viel mehr. Man kann also vermutlich schon sagen, dass es 
irgendwo in der Hierarchie dann ein Verzeichnis gibt, das reinrassig nur 
ein Projekt enthält, aber diese Verzeichnisse selbst sind schon etwas 
verteilt.

Für submodule dürfte das ja so nicht sein?

Muss ich wirklich erst die ganzen Files in jeweils eigene Verzeichnisse 
kopieren?

vlg
Timm

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Timm R. schrieb:
> web          <- Das Wurzelverzeichnis in dem alle Projekte leben
> /web/a/        <- Ein Verzeichnis vom fremden Projekt
> /web/b/c/      <- Ein Verzeichnis vom fremden Projekt
> /web/b/d/      <- Mein Projekt A
> /web/b/e/      <- Mein Projekt B
> /web/f/        <- Mein Projekt A
> /web/g/        <- Mein Projekt B

>
> Für submodule dürfte das ja so nicht sein?

Doch, Du hättest halt direkt unter /web die submodules /a, /f und /g und 
im Verzeichnis /b die submodules /c, /d und /e.

> Muss ich wirklich erst die ganzen Files in jeweils eigene Verzeichnisse
> kopieren?

Das Kopieren würde im Fall von submodules ja git überhemen. (git 
submodule update --recursive)

von DPA (Gast)


Lesenswert?

Torsten R. schrieb:
> git submodule update --recursive

Wobei man bei den Projekten dann, wenn man die neuste Version des 
Submodules will, daran denken muss, dort drin ein "git pull" zu machen, 
falls man nicht sowieso schon dort gearbeitet hat, und dann die Änderung 
auf welchem Commit das Submodul ist im darüberliegenden Git Projekt mit 
"git add pfad/zu/submodul" und "git commit" aktualisieren, und dann die 
Hauptprojekte überall erst mit git pull aktualisieren, bevor man dann 
endlich alle Submodules mit dem "git submodule update --recursive" 
wieder auf den richtigen Commit bringen kann. Das kann sinn machen, wenn 
dir die Relation Projekt Version -> Config Version wichtig ist, 
ansonsten ist es etwas umständlich. Ganz toll ist immer, wenn man 
versehentlich auf einem detached head gearbeitet hat, weil man den "git 
pull" oder "git checkout" davor vergessen hat, usw.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

DPA schrieb:
> Ganz toll ist immer, wenn man
> versehentlich auf einem detached head gearbeitet hat, weil man den "git
> pull" oder "git checkout" davor vergessen hat, usw.

Ja, wenn man ständig aktiv an den submodules arbeitet, sind submodules 
"a pain in the a**". Das würde ich mir auch vorher gut überlegen. Es 
gibt im Netz einige Projekte, die versuchen diese Schmerzen etwas zu 
lindern. Wie gut die funktionieren, kann ich leider nicht beurteilen.

von Timm R. (Firma: privatfrickler.de) (treinisch)


Lesenswert?

Hallo,

sorry, wenn ich mich doof anstelle:

Aber mit submodules, wie oben beschrieben hätte ich ja dann, wenn es 
sagen wir mal 10 Verzeichnisse für das "Stammsystem" gibt und meine zwei 
Projekte jeweils in drei Verzeichnissen wohnen insgesamt 16 submodules?

Komme ich da nicht komplett in des Teufels Küche? Ich wollte es ja 
weniger fehleranfällig als manuelles rsync machen, das hört sich für 
mich aber eher nach dem Gegenteil an.



Ist das Szenario denn so exotisch? Das ist doch faktisch bei allen 
größeren Web-Applikationen so, dass sich eigene Anpassungen und Module 
über verschiedene Verzeichnisse des Stammsystems verteilen? Wie macht 
ihr das denn?

vlg

Timm

von Daniel A. (daniel-a)


Lesenswert?

Timm R. schrieb:
> Komme ich da nicht komplett in des Teufels Küche?

Ja

> Wie macht ihr das denn?

Nunja einerseits gibt es für die meisten Konfigurationsoptionen 
defaults. Eigene Einstellungen lesen Programme dann aus einem Config 
ordner mit Configfiles. Das ist auch bei Webanwendungen so. Unter linux 
packen Packagemaintainer diese Configs normalerweise irgendwo unter 
/etc. Je nach Webapplication liest diese direckt von dort, oder es gibt 
einen Symlink auf die Configs. Die Configs werden dann mit tools wie 
z.B. ansible, salt, etc. verwaltet. Man könnte die Configs natürlich 
auch alle in ein Git projekt packen, und dann für die Anwendungen einen 
Symlink darauf machen. Wenn die Anwendungen eigene git Projekte sind, 
nimmt man die symlinks, falls diese im Projektverzeichnis sind, 
eventuell noch ins .gitignore. Dann fehlt dann aber der Bezug 
Projektversion -> Configversion.

Wobei, ich lasse die Configs einfach wo sie sind, und mache ein 
tägliches Backup davon. Ich habe aber auch (noch) keine Cluster zu 
verwalten, zum glück. Wobei, ich habe ein Fallback system, aber dort 
Kopiere ich einfach alle libvirt-lxc Container von meinem Hauptsystem, 
und nur in den Containern sind dann die Anwendungen und Services. So 
oder so hab ich das Problem einfach nicht.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

Timm R. schrieb:

> Aber mit submodules, wie oben beschrieben hätte ich ja dann, wenn es
> sagen wir mal 10 Verzeichnisse für das "Stammsystem" gibt und meine zwei
> Projekte jeweils in drei Verzeichnissen wohnen insgesamt 16 submodules?

Ich wüste jetzt nicht, warum du aus 10 Verzeichnissen in Deinem 
"Stammsystem" 10 submodules machen möchtest? Wenn Du mit Stammsystem, 
dein Web-Framework oder Deine eigentliche Applikation meinst, dann liegt 
die sinnerigerweise in einem einzigen Repository.

> Komme ich da nicht komplett in des Teufels Küche? Ich wollte es ja
> weniger fehleranfällig als manuelles rsync machen, das hört sich für
> mich aber eher nach dem Gegenteil an.

Da kümmert Git sich ja drum.


> Ist das Szenario denn so exotisch?

Vielleicht hast Du es etwas ungünstig beschrieben. Die 
Web-Applikationen, an denen ich mitgewirkt haben, waren in Rails 
geschrieben und da definiert man an einer Stelle, welche Komponenten das 
System braucht und dann bekommt man die Komponenten auf Knopfdruck in 
exakt definierten und versionierten Versionen installiert (bundler).

> Das ist doch faktisch bei allen
> größeren Web-Applikationen so, dass sich eigene Anpassungen und Module
> über verschiedene Verzeichnisse des Stammsystems verteilen? Wie macht
> ihr das denn?

Submodules können auch Verzeichnisse enthalten.

von tictactoe (Gast)


Lesenswert?

Timm R. schrieb:
> web          <- Das Wurzelverzeichnis in dem alle Projekte leben
> /web/a/        <- Ein Verzeichnis vom fremden Projekt
> /web/b/c/      <- Ein Verzeichnis vom fremden Projekt
> /web/b/d/      <- Mein Projekt A
> /web/b/e/      <- Mein Projekt B
> /web/f/        <- Mein Projekt A
> /web/g/        <- Mein Projekt B

Wenn sich die beiden Teile von Projekt A zusammen in einem 
Git-Repository und die beiden von Projekt B zusammen in einem anderen 
Git-Repository befinden sollen, dann lässt sich das Problem nicht mit 
Git allein lösen. Du brauchst einen anderen Ansatz.

Leider kann ich keine Lösung anbieten. Ich schaue immer, dass alle meine 
Projekte nur Nägel sind, damit ich sie mit meinem Hammer bearbeiten kann 
(ein anderes Werkzeug hab' ich nicht) ;)

von imonbln (Gast)


Lesenswert?

tictactoe schrieb:
> Wenn sich die beiden Teile von Projekt A zusammen in einem
> Git-Repository und die beiden von Projekt B zusammen in einem anderen
> Git-Repository befinden sollen, dann lässt sich das Problem nicht mit
> Git allein lösen. Du brauchst einen anderen Ansatz.

dem  kann ich nur zustimmen! vielleicht könnte man sogar was ganz wildes 
mit git attribute submodules und Templates Hacken, aber dann kann man 
auch gleich alles in einen Git packen denn ausser auf deinen System wird 
es nirgends mehr gehen.


TO du solltest dafür sorgen das eine Structur so in etwa ist

web    <- ist ein git repo
web/a  <- Dein Projekt A
web/b  <- Dein Projekt B
web/c  <- Fremdes Projekt
web/local <- hier ist die logik um die Projekte zu verknupfen.


die Projekte A-C können nun Submodule sein und mit ein paar githooks 
merkt man das kaum noch :) Unterhalb von local oder wie du das nennen 
willst liegt die lokale Logik welche die anderen Projekte nutz, Ich 
empfehle dir bei der Gelegenheit deine Konfigurationen für das Projekt 
als Template Einchecken und dann ein Toolsordner zu erstellen in welchen 
ein Programm liegt das aus den Template sich Konfigurationen für den 
Rechner Halluziniert. Die Fertigen Konfigurationen sollten nicht teil 
deines Projekt sein.

je nach weiteren Setting und Randbedingungen kann jetzt dein CI 
Pipeline, dein Puppet, Ansible, Chef oder dein git mit "git attribute" 
die Konfiguration für jeden Computer in lokale Settings wandeln.

von Bernd K. (prof7bit)


Lesenswert?

Du könntest auch mit Hardlinks arbeiten¹:

/irgend/wo/    <- ist ein ganz normales git repo
/wo/anders/    <- ist auch ein ganz normales git repo


/web/foo       <- hardlink ->   /irgend/wo/foo
/web/bar       <- hardlink ->   /wo/anders/bar
/web/blub/     <- hardlink ->   /irgend/wo/blub/
/web/baz/      <- hardlink ->   /wo/anders/baz/


committen tust Du in den beiden oberen Repos, entwickeln und arbeiten 
tust Du in /web und wenn Du unterhalb von /web eine neue Datei oder 
einen neuen Ordner anlegst der in eins der Repositories aufgenommen 
werden soll musst Du halt einen Hardlink ins jeweilige Repository 
erzeugen.

Nachteil:
* es muss auf der selben Partition liegen.
* erstmalige Installation nach dem Auschecken auf einem neuen Rechner 
erfordert ein kleines Installer-Script das die Hardlinks anlegt damit 
man das nicht jedesmal umständlich und fehlerbehaftet von Hand machen 
muss.

Vorteil:
* Du kannst Dateien aus vielen Repositories wild gemischt kreuz und quer 
im selben Verzeichnis verteilen (vorausgesetzt Du pflegst das oben 
genannte Installer-Script welches das bei Bedarf auf einer neuen 
Festplatte jederzeit wieder vollständig herstellen kann und somit auch 
als Dokumentation fungiert was wohin gelinkt wird)

---

Bessere Lösung: Falls Du voraussetzen (oder per Konvention fordern) 
kannst daß die verschieden Repositories immer unter dem selben Namen und 
in der selben relativen Lage zueinander nebeneinander liegen kannst Du 
in deinem jeweiligen Projektrepository an geeigneter Stelle relative 
Symlinks einchecken die auf Ordner oder Dateien in gemeinsam genutzen 
Repositories zeigen.

/web/framework             <- git repo
/web/projektA              <- git repo
/web/projektA/framework    <- rel. symlink -> ../framework


Vorteil:
* Du brauchst kein Installer-Script, es funktioniert direkt nach dem 
Auschecken weil Symlinks so wie sie sind direkt in git eingecheckt 
werden können.

---

Ich würde erstmal die zweite Methode versuchen, die ist bei geeigneter 
Organisation gut zu handhaben, pflegeleicht und einfach zu durchschauen. 
Wobei die erste auch ihren Charme hat für schnelle Hacks oder für ganz 
spezielle Zwecke in denen ein Ordner Dateien aus mehreren Repositories 
enthalten soll. Ein nützliches Beispiel wäre zum Beispiel daß Du 
bestimmte Dateien unterhalb von /etc versionieren willst und das unter 
Umständen auf mehrere thematisch getrennte Repositories aufteilen 
willst. Dann brauchst Du in jedem dieser Repos noch ein kleines 
installer-Script das nach dem erstmaligen Auschecken die Hardlinks 
erzeugt.

---
¹) Hardlink: https://de.wikipedia.org/wiki/Harter_Link

: Bearbeitet durch User
von DPA (Gast)


Lesenswert?

Bernd K. schrieb:
> Du könntest auch mit Hardlinks arbeiten

Hardlinks auf Verzeichnisse wurden von vielen als schlechte Idee 
erachtet, weshalb die Implementationen der meisten Dateisysteme auf den 
meisten OSen die Erstellung dieser nicht erlauben.

Beitrag #5511513 wurde von einem Moderator gelöscht.
von Bernd K. (prof7bit)


Lesenswert?

DPA schrieb:
> Bernd K. schrieb:
>> Du könntest auch mit Hardlinks arbeiten
>
> Hardlinks auf Verzeichnisse wurden von vielen als schlechte Idee
> erachtet, weshalb die Implementationen der meisten Dateisysteme auf den
> meisten OSen die Erstellung dieser nicht erlauben.

je nachdem was er machen will kommt er vielleicht auch in Variante 1 
komplett mit Symlinks aus. In dem Fall muss die "echte" Datei oder das 
Verzeichnis im Repo liegen und der Symlink im obigen /web Verzeichnis, 
nicht umgekehrt.

Hardlinks sehen halt in jeder Hinsicht (auch für git) genauso aus wie 
reguläre Dateien, daher kann man diesen Umstand für gewisse Hacks 
ausnutzen bei denen es auf beiden Seiten des Links aussehen muss wie 
eine reguläre Datei. Zum Beispiel wenn in seinem /web Ordner irgendwas 
abläuft das voraussetzt daß /web/foo eine reguläre Datei ist und mit 
einem Symlink nicht funktionieren würde, dann würde der Hardlink helfen.

Also erstmal schauen wie weit man mit Symlinks kommt. Man muß halt 
aufpassen in welche Richtung der geht und immer dafür sorgen daß sich im 
Repo die eigentliche Datei befindet und an allen anderen Orten der Link. 
Hardlinks haben keine Richtung, alle Enden sehen gleich aus und sind 
die Datei in jeglicher Hinsicht.

Als Ersatz für einen Hardlink auf ein Verzeichnis könnte man übrigens 
auch einen bind-mount in Erwägung ziehen.

: Bearbeitet durch User
von Timm R. (Firma: privatfrickler.de) (treinisch)


Lesenswert?

Hallo,

faszinierend, ich hätte wirklich gedacht, dass das eine 
Standardproblemstellung ist.

Ich werde einfach pro Projekt einen eigenen Container verwenden, ist 
ressourcenmäßig ja nicht das Problem. Hatte irgendwie gedacht, das ginge 
eleganter. Die Sache mit den Symlinks ist mir für Deployment nicht 
geheuer und fühlt sich für mich irgendwie gefährlich unübersichtlich an. 
Mein Ziel war eigentlich die Komplexität zu reduzieren.

Eigentlich ist die Variante pro Probekt einen Container zu verwenden 
such gar nicht so schlimm.

Viele liebe Grüße und vielen Dank

timm

von Bernd K. (prof7bit)


Lesenswert?

Timm R. schrieb:
> faszinierend, ich hätte wirklich gedacht, dass das eine
> Standardproblemstellung ist.

Git benutzt nun mal (wie übrigens die meisten (alle?) anderen 
Versionskontrollsysteme ebenfalls schon seit jeher) pro Repository auf 
der obersten Ebene ein Verzeichnis mit hartkodiertem Namen (.git) in dem 
es seine Daten hält, daraus folgt direkt das Problem daß bei 2 
verschiedenen Repositories die sich im selben Ordner auf der selben 
Ebene überlagern sollen diese zwangsweise kollidieren müssten. So ein 
Use-Case war von Anfang an auch nie vorgesehen. Ein Ordner - ein 
Repository. Notfalls zumindest ein eigener Unterordner (git submodule).

Wenn man diese Beschränkung als unvermeidbar akzeptiert entwickeln sich 
Konventionen und Best-Practices die diese Problemstellung gar nicht erst 
auftreten lassen. Zum Beispiel indem Frameworks die dafür gedacht sind 
von anderen Projekten verwendet zu werden meist (eigentlich immer) so 
angelegt sind daß sie sich problemlos in komplett eigenen Ordnern 
befinden können, selbst ohne VCS ist schließlich das Konzept "Ordner" 
als gruppierendes Element für zusammengehörende Dateien irgendwie 
sinnvoller als Dateien mehrerer Projekte bunt gemischt in der selben 
Ordnerstruktur sich überlagern zu lassen, es drängt sich geradezu auf.

Die Autoren der Frameworks (oder auch Du jetzt mit Deinem modularen 
Projekt) sehen sich ja alle von Anfang an mit den gleichen Umständen 
konfrontiert und berücksichtigen das zwangsläufig vom Augenblick des 
ersten git init an und entwickeln daher automatisch in die Richtung daß 
man das sauber in verschiedenen Repositories halten kann.

Was übrig bleibt sind wirklich nur noch exotische Use-Cases wo man 
nachträglich ein VCS (oder mehrere) über etwas drüberstülpen will das 
nie zuvor ein VCS gesehen hat und deshalb nicht in dieser Hinsicht 
organisiert wurde, wie zum Beispiel wenn man auf die Idee kommt 
verschiedene Konfigurationsdateien in /etc zu versionieren (was 
eigentlich auch schon wieder irgendwie schräg und überholt ist, sauberer 
geht sowas mit Systemen wie Fabric oder Ansible oder dergleichen und da 
hast Du wieder schön getrennte Ordner die man schön getrennt mit git 
versionieren kann)

---

Die einzige praktikable Möglichkeit die ich sehe das Überlagern zweier 
Repositories im selben Ordner nachträglich dranzuflicken ohne git bis 
ins Innerste umzukrempeln wäre wenn es erlaubt wäre die hartcodierten 
Dateinamen .git* (".git/", ".gitignore") ändern zu können, aber ich 
glaube nicht daß so ein Feature-Request auch nur die leisesten Chancen 
auf Erfolg hätte, eben weil praktisch kein nennenswerter Use-Case 
dafür ins Feld geführt werden kann und auch weil so eine Verwendung 
immer eine vollkommen chaotische Dateisuppe im selben Ornder zur Folge 
hätte bei der man sich nie richtig sicher wäre was nun wohin gehört. 
Womöglich könnte man so etwas wenn man es auf Teufel komm raus wirklich 
braucht schneller mit einem schnell zusammengehackten Wrapperscript 
erreichen das alle .git Ordner und .gitignore Dateien temporär umbenennt 
als es dauern würde so einen Feature-Request in git selbst durchzuboxen.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.