Ausgangssituation

Im Rahmen meiner Beschäftigung mit Joomla 6 entwickle ich derzeit eine eigene Komponente. Das Projekt ist dabei nicht nur ein praktisches Vorhaben, sondern auch eine Möglichkeit, die Joomla-Architektur und die Entwicklung eigener Erweiterungen besser kennenzulernen.

Da ich dabei nicht ausschließlich an einem Rechner arbeite, sondern je nach Situation zwischen meinem Mac und meinem Linux-Rechner wechsle, stellte sich irgendwann die Frage, wie ich den aktuellen Entwicklungsstand zuverlässig auf beiden Systemen verfügbar halte. Genau an diesem Punkt bin ich bei Git und GitHub gelandet.

Das führt anschließend ganz natürlich zu der Frage:
Was ist Git eigentlich und wie funktioniert das Zusammenspiel mit GitHub?

Entwicklung und Testen – zwei unterschiedliche Baustellen

Bisher lag das Projektverzeichnis auf Google Drive. Das hatte zunächst einen offensichtlichen Vorteil: Sowohl der Mac als auch der Linux-Rechner konnten auf dieselben Dateien zugreifen.

Für die eigentliche Entwicklung hatte ich aber noch ein anderes Problem: Die Dateien müssen am Ende auf meinem Joomla-Testserver landen.

Eine Weile habe ich direkt auf dem Server entwickelt. Das funktionierte zwar, war aber auf Dauer ziemlich umständlich. Beim Bearbeiten einer Datei musste die geänderte Datei anschließend über FileZilla wieder auf den Server übertragen werden.

Der andere bisherige Weg war, lokal zu entwickeln und anschließend die komplette Komponente zu packen und auf den Server zu übertragen. Für eine kleine Änderung an einer einzigen PHP-Datei jedes Mal ein neues ZIP zu erzeugen und hochzuladen, ist ebenfalls nicht besonders komfortabel.

Ich brauchte also eigentlich zwei Dinge:

eine Möglichkeit, den Entwicklungsstand zwischen Mac und Linux sauber zu synchronisieren und Änderungen nachvollziehbar zu speichern;
eine möglichst unkomplizierte Möglichkeit, den aktuellen Entwicklungsstand auf meinen Joomla-Testserver zu übertragen.

Damit war Git zunächst die Lösung für den ersten Punkt. Für den zweiten sollte später noch ein separater Weg dazukommen.

Git auf dem Mac einrichten

Als Erstes musste Git auf dem Mac verfügbar sein. Unter macOS gibt es dafür mehrere Möglichkeiten. Auf meinem Rechner war Git bereits vorhanden, weil die Xcode Command Line Tools installiert waren. Ein kurzer Test im Terminal mit zeigte:

$ git --version
git version 2.50.1 (Apple Git-155)

Eine zusätzliche Installation war damit nicht notwendig.

Als Nächstes habe ich ein eigenes Verzeichnis für das Projekt festgelegt. Entscheidend ist dabei, dass die Git-Befehle aus diesem Verzeichnis heraus ausgeführt werden. Git erkennt anhand des dort angelegten .git-Verzeichnisses, zu welchem Repository die Befehle gehören.

Da das Projekt bereits existierte, befanden sich zu diesem Zeitpunkt bereits alle Dateien im Verzeichnis. Das ist aber keine Voraussetzung für git init. Ein Git-Repository kann auch zunächst leer sein und später mit Dateien gefüllt werden.

In meinem Fall wurde also zunächst in das Projektverzeichnis gewechselt:

$ cd /Development/MyComponent

Danach wurde dort das Git-Repository angelegt:

$ git init

Von diesem Zeitpunkt an war das Verzeichnis ein Git-Repository. Alle weiteren Git-Befehle wie git status, git add, git commit oder später git push beziehen sich auf dieses Repository.

Gerade dieser Punkt war für mich anfangs etwas ungewohnt: Git arbeitet grundsätzlich lokal und immer bezogen auf ein bestimmtes Repository. Man muss also nicht irgendwo in VS Codium oder auf GitHub „das Projekt auswählen“. Entscheidend ist, in welchem Verzeichnis man sich im Terminal befindet.

Danach habe ich Git noch einmalig mit meinem Namen und meiner E-Mail-Adresse konfiguriert:

$ git config --global user.name "Max Mustermann"
$ git config --global user.email "Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein."

Damit war die lokale Git-Umgebung vorbereitet.

Das erste Repository

Das Repository wurde nun angelegt. Als nächstes ging es darum, Git mit dem bereits vorhandenen Projektinhalt bekannt zu machen.

Mit

$ git status

kann man jederzeit prüfen, welchen Zustand das Repository gerade hat.

Direkt nach der Initialisierung zeigte Git, dass die vorhanden Dateien noch nicht von der Versionsverwaltung erfasst waren:

On branch main

No commits yet

Untracked files:
administrator/
components/
language/
MyComponent.xml

Git kannte die Dateien also bereits, hatte sie aber noch nicht in die Versionsverwaltung aufgenommen.

Dafür gibt es zunächst den Befehl:

$ git add .

Der Punkt bedeutet dabei: Alle Änderungen im aktuellen Repository für den nächsten Commit vormerken.

Mit einem erneuten

$ git status

werden die Dateien nun unter „Changes to be committed“ angezeigt.

Erst mit git commit entsteht daraus tatsächlich ein neuer Versionsstand:

$ git commit -m "Initial version"

Die Meldung zeigte anschließend unter anderem:

25 files changed, 827 insertions(+)

Damit war der erste Versionsstand des Projekts angelegt.

Der Unterschied zwischen git add und git commit war für mich dabei ein wichtiger Punkt:

Dateien
     ↓
git add
     ↓
für Commit vorgemerkt
     ↓
git commit
     ↓
dauerhaft als Versionsstand gespeichert

Mit

$ git status

kann ich jederzeit kontrollieren, ob seit dem letzten Commit wieder Änderungen vorhanden sind. Nach dem ersten Commit meldete Git:

nothing to commit, working tree clean

Damit war das lokale Repository sauber und der erste Versionsstand festgehalten.

Das Repository auf GitHub

Bis hierhin existierte das Repository ausschließlich auf meinem Mac. Die Versionsverwaltung funktionierte bereits lokal, aber für die Arbeit auf mehreren Rechnern sollte das Repository zusätzlich auf GitHub liegen.

Dafür habe ich auf GitHub ein neues privates Repository für das Projekt angelegt.

Das lokale Repository und das Repository auf GitHub müssen anschließend miteinander verbunden werden. Zunächst habe ich dafür die HTTPS-Adresse des GitHub-Repositories verwendet:

$ git remote add origin https://github.com/MeineFirma/MyComponent.git

Mit

$ git remote -v

kann man anschließend überprüfen, welche Verbindung eingerichtet wurde.

Die Anmeldung bei GitHub

Beim ersten Versuch, den lokalen Versionsstand zu GitHub zu übertragen, kam allerdings eine Fehlermeldung:

remote: Invalid username or token.
remote: Password authentication is not supported for Git operations.

Der Grund: GitHub akzeptiert für Git-Operationen kein normales Account-Passwort mehr.

Statt einen Personal Access Token einzurichten, habe ich mich für SSH entschieden.

Dafür wird auf dem Rechner ein Schlüsselpaar erzeugt. Der private Schlüssel bleibt auf dem eigenen Rechner, während der öffentliche Schlüssel bei GitHub hinterlegt wird.

Auf dem Mac habe ich dazu einen sogenannten Ed25519-Schlüssel erzeugt:

$ ssh-keygen -t ed25519 -C "Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein."

Dabei entstehen zwei Dateien:

~/.ssh/
├── id_ed25519
└── id_ed25519.pub

Die Datei id_ed25519 ist der private Schlüssel und bleibt auf dem Rechner. Die Datei id_ed25519.pub enthält den öffentlichen Schlüssel, der bei GitHub hinterlegt wird.

Anschließend konnte ich die Verbindung testen:

$ ssh -T Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein.<

Nachdem GitHub den Rechner anhand des hinterlegten öffentlichen Schlüssels erkannt hatte, wurde die Remote-Adresse des lokalen Repositorys von HTTPS auf SSH geändert:


$ git remote set-url origin Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein.:MeineFirma/MyComponent.git

Damit war die Authentifizierung eingerichtet und Git konnte ohne Benutzername und Passwort mit GitHub kommunizieren.

Der erste Push

Nachdem die Verbindung zu GitHub eingerichtet war, konnte der bereits vorhandene lokale Versionsstand erstmals auf GitHub übertragen werden.

Dafür wird git push verwendet:

$ git push -u origin main

Dabei stehen die einzelnen Bestandteile für unterschiedliche Dinge:

push überträgt lokale Commits zum entfernten Repository.
origin bezeichnet das zuvor eingerichtete GitHub-Repository.
main ist der Branch, den ich übertragen möchte.
-u legt fest, dass der lokale Branch main künftig dem entfernten Branch origin/main zugeordnet ist.

Das hat einen praktischen Vorteil: Beim nächsten Push reicht anschließend einfach:

$ git push

Git weiß dann bereits, wohin der lokale main-Branch übertragen werden soll.

Nach dem erfolgreichen Push war der erste Versionsstand nicht mehr nur lokal vorhanden, sondern auch auf GitHub gespeichert.

Damit war der erste wichtige Schritt geschafft: Mein Projekt hatte nun eine Versionsgeschichte und ein zentrales Repository, auf das ich von meinen verschiedenen Entwicklungsrechnern aus zugreifen konnte.

Arbeiten mit mehreren Rechnern

Damit war der erste Stand auf GitHub. Jetzt kam der eigentliche Grund für die ganze Einrichtung zum Tragen: Ich wollte mit demselben Projekt sowohl auf dem Mac als auch auf meinem Linux-Rechner arbeiten können.

Auf dem zweiten Rechner musste ich das Repository nicht noch einmal mit git init anlegen. Stattdessen wird ein bereits vorhandenes GitHub-Repository mit git clone lokal kopiert:

$ git clone Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein.:MeineFirma/MyComponent.git

Dabei erstellt Git automatisch das lokale Verzeichnis und richtet darin auch das .git-Verzeichnis ein.

Damit hatte ich auf beiden Rechnern ein eigenes lokales Repository:

Mac                         Linux
│                           │
└── MyComponent             └── MyComponent
        │                           │
        └──────── GitHub ───────────┘

Die lokalen Verzeichnisse müssen dabei weder am gleichen Ort liegen noch denselben Pfad haben. Entscheidend ist nur, dass beide mit demselben entfernten Repository verbunden sind.

Wenn ich auf einem Rechner Änderungen vorgenommen und anschließend mit git push zu GitHub übertragen habe, konnte ich auf dem anderen Rechner mit

$ git pull

den aktuellen Stand abrufen.

Damit war der grundlegende Wechsel zwischen meinen beiden Entwicklungsrechnern möglich:

Dabei wurde mir auch klar, dass Git nicht einfach nur Dateien zwischen zwei Rechnern synchronisiert. Git synchronisiert Versionsstände. Jeder Rechner kann zunächst unabhängig arbeiten, und Git kann anschließend feststellen, welche Änderungen auf welchem Stand vorhanden sind.

Und wie kommen die Dateien auf den Testserver?

Git löst zwar die Versionsverwaltung und den Austausch zwischen Mac und Linux, aber die Dateien müssen für den Test natürlich weiterhin auf den Joomla-Testserver.

Dafür habe ich SFTPresso als Erweiterung für VS Codium eingerichtet. Damit kann ich den Inhalt meines lokalen Projektverzeichnisses per FTP über TLS auf den Server übertragen.

Die Konfiguration legt dabei fest, dass der Inhalt des Projektverzeichnisses direkt in das gewünschte /tmp-Verzeichnis auf dem Server übertragen wird.

Dabei werden bestimmte lokale Verzeichnisse wie .git und .vscode vom Upload ausgeschlossen. Das Git-Repository und die lokale SFTPresso-Konfiguration bleiben somit auf dem Entwicklungsrechner und landen nicht auf dem Server.

Der Ablauf sieht damit inzwischen so aus:

                GitHub
               ↙      ↘
            Mac       Linux
             │          │
             └── SFTPresso ──┘
                     │
                    FTPS
                     ↓
                Joomla-Server
                     │
                   /tmp

Damit sind Versionsverwaltung und Deployment voneinander getrennt: Git kümmert sich um die Entwicklung und Versionsgeschichte, SFTPresso um die Übertragung der aktuellen Dateien auf den Testserver.