Git-Workflow für Shopware-Plugins: Eigenes Repository oder GitHub? (Teil 3)
Serie: Professionelle Shopware-Entwicklungsumgebung
- Entwicklungsumgebung einrichten (DDEV + Docker)
- Git-Workflow für Plugin-Entwicklung (dieser Artikel)
- Testen und Qualitätssicherung
- Deployment und Updates
Du hast deine Entwicklungsumgebung aufgesetzt und ein erstes Plugin-Gerüst erstellt. Aber was passiert, wenn du eine Änderung machst, die alles kaputt macht? Ohne Git hast du ein Problem. Mit Git hast du einen Rücksprungpunkt. In diesem Teil zeige ich dir, wie du Versionskontrolle für deine Shopware-Plugins einrichtest — und warum das auch als Solo-Entwickler keine Option, sondern Pflicht ist.
Warum Versionskontrolle?
Stell dir vor, du arbeitest an einer Versandkosten-Berechnung. Du änderst drei Dateien, testest im Browser — und plötzlich funktioniert der gesamte Checkout nicht mehr. Ohne Git fängt jetzt das hektische Suchen an: Was habe ich geändert? Welche Datei war es? War der Stand von gestern noch korrekt?
Mit Git ist die Antwort ein Einzeiler: git diff zeigt dir exakt, was sich geändert hat. git checkout -- . setzt alles auf den letzten gesicherten Stand zurück. Kein Raten, kein Suchen.
Aber Versionskontrolle kann noch mehr:
- Code-History: Jeder Stand deines Plugins ist gespeichert. Du kannst jederzeit nachschauen, wann du eine bestimmte Funktion eingebaut hast — und warum.
- Parallele Entwicklung: Mit Branches arbeitest du an neuen Features, ohne den stabilen Stand zu gefährden.
- Zusammenarbeit: Sobald ein zweiter Entwickler am Plugin mitarbeitet, ist Git keine Empfehlung mehr — es ist die einzige sinnvolle Option.
- Backup: Dein Code liegt nicht nur auf einem Rechner. Er ist auf dem Server, auf GitHub, oder auf beidem.
Auch als Solo-Entwickler wirst du Git nach einer Woche nicht mehr missen wollen. Spätestens wenn du einen Bug in der Produktion fixen musst und gleichzeitig an einem neuen Feature arbeitest, wirst du froh sein, dass du Branches hast.
Zwei Wege zum eigenen Repository
Für dein Shopware-Plugin brauchst du ein zentrales Repository, in das du deinen Code pushst. Dafür gibt es zwei sinnvolle Optionen — und beide sind valide.
Option A: Eigenes Git-Repository auf dem VPS
Wenn du bereits einen VPS für deine Entwicklungsumgebung betreibst, liegt es nahe, auch dein Repository dort zu hosten. Du erstellst dafür ein sogenanntes Bare-Repository — ein Repository ohne Arbeitskopie, das nur als zentraler Speicher dient.
Bare-Repository auf dem Server anlegen
Verbinde dich per SSH mit deinem Server:
ssh devbox
mkdir -p /workspace/git/RcMeinPlugin.git
cd /workspace/git/RcMeinPlugin.git
git init --bare
Das --bare ist wichtig: Es erstellt ein Repository ohne Arbeitsverzeichnis. Niemand arbeitet direkt auf dem Server an den Dateien — der Server nimmt nur Pushes entgegen und speichert die History.
Lokal verbinden und ersten Commit pushen
cd /pfad/zum/plugin
git init
git remote add origin devbox:/workspace/git/RcMeinPlugin.git
git add -A
git commit -m "Initiales Plugin-Setup"
git push -u origin main
Ab jetzt kannst du lokal arbeiten, committen und auf den Server pushen. Push und Pull gehen über dein lokales Netzwerk oder VPN — das bedeutet Millisekunden statt Sekunden.
Vorteile
- Geschwindigkeit: Push und Pull laufen über LAN oder VPN — spürbar schneller als über das Internet
- Volle Kontrolle: Deine Daten liegen auf deinem Server, nicht bei einem externen Anbieter
- Kein Vendor-Lock-in: Du bist an keinen Dienst gebunden
- Private Entwicklung: Kein Konto bei einem Drittanbieter nötig, keine Sichtbarkeitseinstellungen
GitHub jederzeit nachrüsten
Das Schöne an Git: Du kannst jederzeit ein zweites Remote hinzufügen. Wenn du dein Plugin später auf GitHub veröffentlichen willst, ist das ein Dreizeiler:
git remote add github git@github.com:user/RcMeinPlugin.git
git push github main
Dein VPS bleibt das Haupt-Remote für die tägliche Arbeit. GitHub dient als Backup, für Open-Source-Veröffentlichung oder für CI/CD.
Option B: Direkt mit GitHub arbeiten
Wenn du keinen eigenen Server betreibst oder den Verwaltungsaufwand scheust, kannst du dein Repository direkt auf GitHub anlegen. Das ist der einfachere Weg — besonders für Einsteiger.
Repository erstellen und verbinden
Du kannst das Repository über die GitHub-Weboberfläche erstellen oder direkt über die Kommandozeile:
cd /pfad/zum/plugin
git init
git remote add origin git@github.com:user/RcMeinPlugin.git
git add -A
git commit -m "Initiales Plugin-Setup"
git push -u origin main
Vorteile
- Kein Server nötig: Kein eigenes Repository verwalten, keine Backups einrichten
- CI/CD sofort verfügbar: GitHub Actions lassen sich direkt nutzen — automatische Tests, Code-Analyse, Deployment
- Projekt-Management: Issues, Pull Requests, Projekt-Boards — alles integriert
- Community: Wenn du dein Plugin als Open Source veröffentlichst, ist GitHub die etablierte Plattform
Nachteile
- Abhängigkeit: Dein Code liegt bei einem externen Dienst. Wenn GitHub offline ist, kannst du nicht pushen.
- Geschwindigkeit: Push und Pull laufen über das Internet — bei großen Repositories oder langsamer Leitung spürbar
- Privatsphäre: Auch bei privaten Repositories liegen deine Daten auf fremden Servern
Welche Option passt zu dir?
Beide Wege sind absolut valide. Wenn du bereits einen VPS für deine Entwicklungsumgebung hast, ist Option A der logische Schritt — du nutzt vorhandene Infrastruktur und hast maximale Kontrolle. Wenn du schnell starten willst und keinen eigenen Server betreibst, ist GitHub die pragmatische Wahl. Du kannst die Entscheidung auch jederzeit ändern: Ein Git-Remote lässt sich in Sekunden hinzufügen oder entfernen.
Die richtige .gitignore für Shopware-Plugins
Bevor du deinen ersten Commit machst, brauchst du eine .gitignore-Datei. Sie legt fest, welche Dateien nicht ins Repository gehören. Das klingt trivial, ist aber einer der häufigsten Fehler bei Einsteigern: Wer alles committet, hat schnell ein aufgeblähtes Repository mit sensiblen Daten drin.
Hier ist die .gitignore, die du für jedes Shopware-Plugin verwenden solltest:
# Abhängigkeiten — werden über Composer installiert, nicht versioniert
/vendor/
# Cache und Build-Artefakte
/var/
.php-cs-fixer.cache
.phpunit.cache
.phpunit.result.cache
# IDE-Konfigurationen — jeder Entwickler nutzt eigene Einstellungen
.idea/
.vscode/
*.swp
*.swo
# Betriebssystem-Dateien
.DS_Store
Thumbs.db
desktop.ini
# Umgebungskonfiguration — enthält sensible Daten
.env
.env.local
.env.*.local
# Node.js (falls Storefront-Assets gebaut werden)
/node_modules/
Lass uns die einzelnen Gruppen durchgehen — denn jede hat ihren Grund.
vendor/ — Abhängigkeiten gehören nicht ins Repository
Das vendor/-Verzeichnis enthält alle Pakete, die Composer herunterlädt. Bei einem typischen Shopware-Plugin können das hunderte Megabytes sein. Diese Dateien werden durch composer install automatisch generiert — sie ins Repository zu packen, wäre wie ein Backup deines Downloads-Ordners. Unnötiger Ballast, der bei jedem Update zu riesigen Diffs führt.
Die composer.json und composer.lock hingegen gehören ins Repository. Sie definieren exakt, welche Versionen installiert werden sollen. Damit kann jeder Entwickler (oder dein Server) mit einem einzigen Befehl den identischen Stand herstellen.
var/ — Cache und temporäre Dateien
Shopware legt im var/-Verzeichnis Cache-Dateien, Logs und temporäre Daten ab. Die werden bei jedem cache:clear neu generiert und sind maschinenspezifisch. Ein Cache vom Entwicklungsrechner ist auf dem Produktivserver nutzlos — schlimmer noch, er kann Probleme verursachen.
IDE-Dateien — persönliche Einstellungen
.idea/ (PhpStorm), .vscode/ (VS Code) und Swap-Dateien wie *.swp enthalten die persönlichen Editor-Einstellungen des jeweiligen Entwicklers. Schriftgröße, Farbschema, Debugger-Konfiguration — das gehört nicht in den gemeinsamen Code. Jeder Entwickler richtet seine IDE so ein, wie er am besten arbeiten kann.
.env — Sensible Daten, niemals versionieren
Die .env-Datei enthält Datenbankpasswörter, API-Keys, Server-URLs und andere Konfiguration, die sich zwischen Umgebungen unterscheidet. Diese Datei darf unter keinen Umständen ins Repository. Ein versehentlich gepushtes Datenbankpasswort ist ein Sicherheitsrisiko — und die Git-History vergisst nichts. Selbst wenn du die Datei später löschst, bleibt sie in der History erhalten.
node_modules/ — JavaScript-Abhängigkeiten
Falls dein Plugin Storefront-Assets mitbringt, hast du möglicherweise ein package.json und ein node_modules/-Verzeichnis. Für node_modules gilt dasselbe wie für vendor/: Es wird durch npm install generiert und kann tausende Dateien umfassen. Ins Repository gehört nur die package.json (und package-lock.json).
Saubere Commits schreiben
Ein Commit ist mehr als ein Speicherpunkt. Er ist eine Nachricht an dein zukünftiges Ich — und an jeden, der jemals an diesem Code arbeiten wird. Die Qualität deiner Commit-Messages entscheidet darüber, ob die Git-History nützlich oder nutzlos ist.
Die Grundregel: Ein Commit = eine logische Änderung
Nicht drei Features auf einmal. Nicht „ein bisschen hier, ein bisschen da“. Jeder Commit sollte genau eine Sache tun — und die Commit-Message sollte diese Sache klar benennen.
Schlecht:
Verschiedene Änderungen
Update
Fix
asdf
Gut:
Versandkosten-Berechnung für Auslandslieferungen ergänzt
Mindestbestellwert-Prüfung im Checkout-Subscriber korrigiert
Konfigurationsfelder für Steuer-Mapping hinzugefügt
Ob du auf Deutsch oder Englisch schreibst, ist Geschmackssache — aber bleib konsistent. In einem deutschsprachigen Team sind deutsche Messages absolut in Ordnung.
Vor jedem Commit: git status
Mach dir das zur Gewohnheit. Bevor du commitest, schau dir an, was sich geändert hat:
# Was hat sich geändert?
git status
# Details anzeigen
git diff
# Gezielt Dateien stagen
git add src/Subscriber/CheckoutSubscriber.php
git add src/Service/ShippingCalculator.php
# Commit erstellen
git commit -m "Versandkosten-Berechnung für Ausland ergänzt"
So vermeidest du, dass versehentlich Debug-Dateien, temporäre Testdaten oder andere Überbleibsel im Commit landen.
Branching-Basics
Ein Branch ist eine eigenständige Arbeitskopie deines Codes. Du zweigst vom Hauptstrang ab, arbeitest an einem Feature, und führst die Änderungen erst zusammen, wenn alles fertig und getestet ist. Der Hauptstrang bleibt währenddessen stabil.
So funktioniert es in der Praxis
Nehmen wir an, du willst eine Export-Funktion für Versandkosten einbauen:
# Neuen Branch erstellen und wechseln
git checkout -b feature/versandkosten-export
# ... arbeiten, testen, committen ...
git add src/Service/ShippingExporter.php
git commit -m "CSV-Export für Versandkostenregeln implementiert"
git add src/Controller/ExportController.php
git commit -m "Admin-Route für Versandkosten-Export ergänzt"
# Zurück zum Hauptbranch
git checkout main
# Feature-Branch zusammenführen
git merge feature/versandkosten-export
Warum nicht einfach alles auf main committen?
Solange du alleine an einem kleinen Feature arbeitest, funktioniert das. Aber sobald du an mehreren Dingen gleichzeitig arbeitest, wird es chaotisch. Stell dir vor:
- Du baust gerade die Export-Funktion (halb fertig, noch nicht getestet)
- Ein Kunde meldet einen kritischen Bug im Checkout
Ohne Branches hast du jetzt halbfertigen Feature-Code und musst trotzdem einen Fix liefern. Mit Branches wechselst du einfach zurück auf main, erstellst einen hotfix/checkout-bug-Branch, fixst den Fehler und lieferst. Dein halbfertiges Feature wartet sicher in seinem eigenen Branch.
Typische Branch-Struktur
| Branch | Zweck |
|---|---|
main | Stabiler, getesteter Stand — immer lauffähig |
feature/* | Neue Funktionen, z.B. feature/steuer-mapping |
hotfix/* | Dringende Bugfixes für den Produktivstand |
refactor/* | Code-Umbauten ohne neue Funktionalität |
Du musst kein kompliziertes Branching-Modell wie Git Flow einführen. Für die Plugin-Entwicklung reichen main und Feature-Branches. Wichtig ist nur die Grundregel: Auf main liegt immer ein funktionierender Stand.
Der tägliche Workflow auf einen Blick
Hier der typische Ablauf für einen Arbeitstag an deinem Shopware-Plugin:
# 1. Neuen Branch für das aktuelle Feature
git checkout -b feature/mein-neues-feature
# 2. Arbeiten, Änderungen prüfen
git status
git diff
# 3. Gezielt stagen und committen
git add src/relevante-datei.php
git commit -m "Aussagekräftige Beschreibung der Änderung"
# 4. Auf den Server pushen
git push origin feature/mein-neues-feature
# 5. Wenn fertig: in main zusammenführen
git checkout main
git merge feature/mein-neues-feature
git push origin main
Das klingt nach vielen Schritten — wird aber nach ein paar Tagen zur Routine. Und diese Routine schützt dich vor den Momenten, in denen alles schiefgeht.
Wie geht es weiter?
Dein Plugin ist jetzt versioniert, deine Commits sind sauber, und du hast einen Workflow, der mit dir wachsen kann. Im nächsten Teil der Serie schauen wir uns an, wie du dein Plugin automatisiert testest und mit Code-Qualitäts-Tools sicherstellst, dass nichts kaputtgeht.
Alle Teile der Serie:
- Entwicklungsumgebung einrichten (DDEV + Docker)
- Das erste Plugin-Grundgerüst
- Git-Workflow für Plugin-Entwicklung (dieser Artikel)
- Testen und Qualitätssicherung
- Deployment und Updates
Die gezeigten Code-Beispiele dienen zur Veranschaulichung. Nutzung auf eigene Verantwortung. Mehr dazu