Hier entwickeln wir Microservices und IT-Systemen für die Cloud mit Java oder Kotlin. Für die einfache Nutzung von Datenbanken (z.B. MongoDB), Security- oder Frontend-Technologien stelle ich das Spring Framework mit dem Spring Boot Projekt vor. Mit Clean Code Prinzipen und Test-Automatisierungstechniken zeige ich, wie Wartbarkeit und Qualität sichergestellt wird.
Ob Entwicklung, Test, Betrieb oder Projektmanagement – Git ist nicht nur ein Thema für Developer. Es ist ein zentrales Werkzeug, das die Zusammenarbeit im gesamten IT-Team unterstützt und absichert. Doch was macht Git eigentlich so wertvoll?
Zentraler Zugriff auf den Code
Mit Git arbeitet das ganze Team an einer gemeinsamen Codebasis. Egal ob Backend, Frontend, Testautomatisierung oder Infrastruktur-as-Code – alle Dateien liegen im selben Repository. Das sorgt für Transparenz und verhindert, dass einzelne Teammitglieder mit unterschiedlichen Versionen arbeiten. Jeder kann nachvollziehen, wie sich der Code entwickelt und welche Änderungen aktuell sind.
Nachvollziehbarkeit von Änderungen
Git protokolliert jede Änderung. Wer hat wann was geändert – und warum? Diese Informationen sind Gold wert, wenn man verstehen möchte, warum ein Fehler entstanden ist oder wie ein Feature genau implementiert wurde. Gute Commit-Nachrichten und sauber strukturierte Branches machen es möglich, die Entwicklung lückenlos nachzuvollziehen.
Sicherheit durch Versionierung
Mit Git ist jede Änderung gesichert. Man kann jederzeit auf einen früheren Stand zurückspringen – etwa wenn nach einem Deployment plötzlich ein Fehler auftritt. Git fungiert damit wie ein intelligentes Backup-System für die gesamte Codebasis. Es schützt nicht nur vor Datenverlust, sondern gibt auch Sicherheit bei Experimenten und schnellen Hotfixes.
Git Basics – Die wichtigsten Konzepte
Repository
Ein Repository ist der Speicherort für den Projektcode und dessen gesamte Versionsgeschichte. Man unterscheidet zwischen zwei Arten:
Das lokale Repository liegt auf dem eigenen Rechner. Hier arbeitet man direkt am Code, führt Änderungen durch und sichert diese in Form von Commits.
Das Remote Repository liegt auf einem Server, zum Beispiel bei GitHub oder GitLab. Es dient als zentrale Anlaufstelle für das gesamte Team. Von hier wird der Code verteilt, synchronisiert und zusammengeführt.
Ein typischer Arbeitsablauf beginnt damit, dass man ein Remote Repository einmalig klont und anschließend lokal daran arbeitet.
Commit und Push
Änderungen am Code werden in sogenannten Commits gesichert. Jeder Commit enthält eine Momentaufnahme der geänderten Dateien sowie eine Nachricht, die beschreibt, was geändert wurde. So entsteht eine nachvollziehbare Änderungshistorie.
Sobald ein oder mehrere Commits lokal erstellt wurden, kann man sie durch einen Push an das Remote Repository übertragen. Erst dann werden die Änderungen für andere sichtbar.
Pull
Während man selbst Änderungen vornimmt, arbeitet auch das Team weiter. Damit die eigene lokale Version aktuell bleibt, werden die Änderungen anderer Teammitglieder regelmäßig aus dem Remote Repository abgerufen. Dieser Vorgang heißt Pull.
Branch
Ein Branch ist ein Entwicklungszweig, in dem Änderungen isoliert vorgenommen werden können. Auf diese Weise lassen sich neue Features, Bugfixes oder Experimente entwickeln, ohne den Hauptzweig des Projekts zu beeinflussen.
Ein Projekt hat in der Regel einen Hauptbranch (z. B. main oder master), von dem aus neue Branches erstellt und später wieder integriert werden.
Merge
Wenn ein Branch fertig entwickelt wurde, sollen die Änderungen wieder in den Hauptzweig einfließen. Mit einem Merge werden die beiden Zweige zusammengeführt, wobei die komplette Entwicklungshistorie erhalten bleibt. Git erstellt dabei einen zusätzlichen Merge-Commit, der die Zusammenführung dokumentiert und die Nachvollziehbarkeit sicherstellt.
Log und History
Git speichert jede Änderung mit Zeitstempel, Autor und Nachricht. Über die Historie lässt sich jederzeit nachvollziehen, wer wann welche Änderung vorgenommen hat. Das ist besonders hilfreich, wenn man verstehen möchte, warum ein bestimmter Fehler auftritt oder wie sich ein Feature entwickelt hat.
Video mit Demo zu diesem Abschnitt.
GIT im täglichen Einsatz & Best Practices
Git Kommandozeile oder Tools
Git kann auf unterschiedliche Weise genutzt werden – je nach persönlicher Vorliebe und eingesetztem Werkzeug. Viele moderne Entwicklungsumgebungen wie IntelliJ IDEA oder Visual Studio Code haben Git bereits integriert. So lassen sich typische Aktionen wie Commit, Pull oder das Anlegen von Branches direkt aus der IDE heraus durchführen – ohne zwischen Programmen wechseln zu müssen.
Alternativ kann man Git auch direkt über die Kommandozeile bedienen. Das bietet maximale Kontrolle und hilft dabei, die Abläufe im Hintergrund besser zu verstehen. Besonders für wiederkehrende Aufgaben oder automatisierte Prozesse ist die Kommandozeile oft die bevorzugte Wahl.
Ein weiterer beliebter Weg ist die Nutzung von TortoiseGit. Dieses Tool integriert sich direkt in den Windows Explorer und macht viele Git-Funktionen über das Kontextmenü mit der rechten Maustaste zugänglich. Gerade wer häufig mit Dateien und Ordnern arbeitet, profitiert von dieser nahtlosen Einbettung in die gewohnte Arbeitsumgebung.
Bei kleinen Änderung
Pull first
Bevor man Änderungen an einem Projekt vornimmt, sollte man sich angewöhnen, zunächst einen Pull durchzuführen. Damit stellt man sicher, dass man auf dem aktuellen Stand des Remote-Repositories arbeitet und alle Änderungen der Teammitglieder berücksichtigt.
Gerade bei kleineren Anpassungen – etwa an Konfigurationsdateien, Texten oder Dokumentation – ist die Gefahr groß, dass mehrere Personen gleichzeitig dieselbe Datei bearbeiten. Ein vorheriger Pull reduziert das Risiko von Merge-Konflikten erheblich und sorgt dafür, dass die eigenen Änderungen reibungslos integriert werden können.
Diese einfache Gewohnheit spart im Alltag viel Zeit und vermeidet unnötige Unterbrechungen im Arbeitsfluss.
Review vor Commit & Push
Bevor Änderungen committet und gepusht werden, sollte man sie kurz überprüfen. Ein Blick auf die geänderten Dateien und Inhalte hilft, versehentliche Änderungen oder temporäre Code-Anpassungen zu erkennen. Dieser Schritt verbessert die Qualität und verhindert unnötige Korrekturen im Nachhinein.
Gute Commit-Message mit Ticket-Referenz
In der Teamarbeit ist eine eindeutige Ticket-Referenz in der Commit-Message besonders wichtig. Sie ermöglicht es, jede Änderung direkt einer Aufgabe oder einem Fehlerbericht zuzuordnen. Idealerweise folgt die Nachricht einem einheitlichen Format im Team – zum Beispiel:
JIRA-123: Validation for email field added
Ein kurzer, präziser Satz reicht meist aus, wenn er zusammen mit der Ticket-ID den Kontext klar macht.
Ein Commit – eine Änderung
Ein Commit sollte sich immer auf genau eine inhaltliche Änderung konzentrieren. Wenn man beispielsweise gleichzeitig die Texte in der Benutzeroberfläche ändert und ein neues Logging einführt, gehören diese Änderungen in getrennte Commits. So bleibt die Historie nachvollziehbar, und einzelne Änderungen lassen sich bei Bedarf gezielt zurückverfolgen oder rückgängig machen.
Revert statt Löschen
Ein Revert nimmt eine Änderung zurück, indem ein neuer Commit erzeugt wird, der genau das Gegenteil der ursprünglichen Änderung macht. Der ursprüngliche Commit bleibt in der Historie erhalten, sodass der Verlauf vollständig nachvollziehbar bleibt – es gibt also keine Löschung, sondern eine bewusste Korrektur.
Ein Revert muss nicht unbedingt einen Fehler beheben. Manchmal hat man bewusst etwas ausprobiert, das später nicht mehr benötigt wird, und möchte es daher zurücknehmen. Dabei entstehen nach einem Revert zwei Commits im Branch: der ursprüngliche Commit und der Revert-Commit.
Obwohl es grundsätzlich möglich ist, Commits zu löschen, ist dies in der Praxis eher umständlich.
Große Änderung mit feature-Branches
Bei größeren Änderungen, die umfangreiche Anpassungen oder die Entwicklung neuer Funktionen betreffen, ist es ratsam, einen Feature-Branch zu verwenden. Ein Feature-Branch ist ein separater Entwicklungszweig, der vom Hauptzweig (z. B. main oder master) abzweigt und speziell für die Entwicklung eines bestimmten Features oder einer größeren Änderung gedacht ist.
Der Vorteil von Feature-Branches liegt darin, dass man isoliert an neuen Funktionen arbeiten kann, ohne die Stabilität des Hauptzweigs zu gefährden. Änderungen im Feature-Branch werden lokal entwickelt, getestet und überprüft, bevor sie durch einen Merge oder Pull-Request in den Hauptzweig integriert werden.
Mit dieser Methode bleibt der Hauptzweig stets stabil und funktionsfähig, während das Team parallel an neuen Features oder Verbesserungen arbeitet. Feature-Branches bieten außerdem den Vorteil, dass mehrere Teammitglieder gleichzeitig an verschiedenen Features arbeiten können, ohne dass sich ihre Änderungen gegenseitig beeinflussen.
Rebase
Ein Rebase wird häufig eingesetzt, bevor ein Feature-Branch in den master- oder main-Branch gemerged wird. Ziel ist es, den Feature-Branch auf den aktuellen Stand des Hauptzweigs zu bringen, um spätere Merge-Konflikte zu vermeiden. Dabei werden die eigenen Commits so umgehängt, als wären sie auf dem aktuellen Stand von master entstanden.
Technisch gesehen verschiebt Git dabei die Commits aus dem Feature-Branch auf die aktuelle Spitze des Hauptzweigs. So entsteht eine lineare Historie, in der alle Änderungen sauber aufeinander folgen – ganz ohne zusätzlichen Merge-Commit.
Empfehlung: Merge mit Squash
Bevor ein Feature-Branch in den master- oder main-Branch gemerged wird, empfiehlt es sich, alle Commits aus dem Feature-Branch zu einem einzigen Commit zusammenzufassen – dieser Vorgang wird „Squash“ genannt. Gerade bei der Entwicklung eines Features entstehen oft viele kleine Commits, die aus Sicht der Projekt-Historie nicht einzeln relevant sind.
Ein Merge mit Squash sorgt dafür, dass im Hauptzweig nur ein klar benannter Commit auftaucht, der das gesamte Feature beschreibt. Das hält die Historie übersichtlich und hilft, die Entwicklungsschritte später leichter nachzuvollziehen.
Diese Methode ist besonders nützlich bei der Arbeit im Team, da sie Wildwuchs in der Historie vermeidet und den Überblick über eingeführte Features erleichtert.
Git Blame - wer war es?
Mit dem Git-Befehl blame kann man herausfinden, wer eine bestimmte Zeile in einer Datei zuletzt geändert hat – und in welchem Commit das passiert ist. Das ist besonders hilfreich, wenn man verstehen möchte, warum ein bestimmter Code geschrieben wurde oder wer bei Rückfragen der richtige Ansprechpartner ist.
Git Diff - was hat sich genau geändert?
Mit git diff kann man sich Unterschiede zwischen zwei Versionen von Dateien anzeigen lassen – etwa zwischen dem aktuellen Stand im Arbeitsverzeichnis und dem letzten Commit oder zwischen zwei Branches. So sieht man genau, welche Zeilen hinzugefügt, geändert oder entfernt wurden.
Tags
Tags in Git sind Markierungen, mit denen bestimmte Commits eindeutig gekennzeichnet werden – etwa für Versionen, die für den Produktivbetrieb freigegeben wurden. Ein Tag ist fest mit einem bestimmten Stand des Codes verbunden und verändert sich nicht mehr.
Tags eignen sich besonders gut zur Kennzeichnung von produktionsreifen Versionen. Anstatt separate Branches wie release oder prod zu pflegen, kann direkt ein Tag auf den Commit gesetzt werden, der in Produktion geht. So bleibt die Historie klar und nachvollziehbar: Man erkennt genau, welche Version zu welchem Zeitpunkt deployed wurde.
In vielen Projekten werden Tags nach dem Prinzip der semantischen Versionierung vergeben – zum Beispiel v1.0.5. So lässt sich schnell erkennen, ob es sich um einen neuen Funktionsumfang, ein Bugfix oder eine größere Änderung handelt.
Fazit
Git ist weit mehr als nur ein Versionierungstool – es ist ein unverzichtbares Fundament moderner Softwareentwicklung und ein Schlüsselbestandteil effektiver Teamzusammenarbeit. Git ermöglicht nicht nur die Verwaltung von Code, sondern spielt auch eine zentrale Rolle in modernen Release- und Deployment-Prozessen. Durch die enge Integration in Build- und Deployment-Pipelines können Änderungen im Git-Repository automatisch ganze Prozesse anstoßen, von der Erstellung von Builds bis hin zum Deployment in die Produktion. Dies fördert eine nahtlose und automatisierte Entwicklung und sorgt für eine effiziente, fehlerresistente Bereitstellung von Software.
Mit Spring können zeitgesteuerte Aufgaben in Java Code integriert werden. CronJobs wie wir sie in Linux kennen, definieren wir mit Spring einfach per Annotation. In diesem Artikel zeige ich wie das geht und wie Spring die CronJobs entsprechend unserer Definition ausführt. Was ist ein CronJob? Unter CronJob verstehen wir die zeitlich gesteuerte Ausführung eines Kommandos zur Erledigung einer Aufgabe bzw. eines Jobs. Das Kommando wird durch einen bestimmten Zeitpunkt oder eine zeitliche Bedingung angestoßen. Typische Beispiele für durch CronJobs gestartete Aufgaben sind: Regelmäßiges Aufräumen der Datenbank - z. B. um veraltete Daten zu löschen oder DSGVO konform persönliche Daten nach einer definierten Zeit zu löschen. Wöchentlicher Versand von Newslettern oder Werbung per Email Nächtliche Datenbank-Backups Monatliches Erstellen von Rechnungen (z.B. Telefon-Rechnung) Das Betriebssystem Linux bietet crontab zum Erstellen von CronJobs an. Mit crontab könnten wir eine Spring Anwendung star...
In diesem Blog-Post besprechen wir die Basics von Spring: Spring Beans und wie man diese miteinander vernetzt bzw. referenziert (Dependency Injection). Den kompletten Code zu diesem Blog-Post findet ihr in GitHub: https://github.com/elmar-brauch/beans Spring Bean Spring Beans sind Java Objekte, die durch den Spring IoC Container instanziiert und verwaltet werden. Der IoC (Inversion of Control) Container erstellt Beans anhand einer Bean Definition, die der Entwickler in Form von Annotationen oder xml Konfiguration bereitstellt. IoC ist ein Umsetzungsparadigma und bedeutet Steuerungsumkehr. Im Kontext des Spring Frameworks versteht man darunter, dass das Framework die Erstellung des Objektnetzes (Beans) anstelle des Entwicklers übernimmt. In vorherigen Blog-Artikel haben wir bereits Projekte mit Spring Boot aufgesetzt, siehe z.B. microservices-mit-spring-boot-erstellen.html . In diesen Projekten verwendeten wir die Annotation @SpringBootApplication , welche eine Ag...
Authentifizierung mit OpenID Connect geht einfach dank Spring Boot. Wir bauen den Login Deiner Web-Anwendung mit dem Autorisierungsserver Deiner Firma. Wie wir dazu OpenID Connect mit Spring Boot 3 konfigurieren, zeige ich in diesem Blog-Artikel. OpenID Connect - Authorization Code Prozess OpenID Connect ist ein Single Sign-On Login-Verfahren. Zur Umsetzung komplexer Anwendungsfälle verwenden größere Firmen meist verteilte Systeme. Damit der Benutzer z. B. beim Online-Shopping den Systemwechsel von Produktseiten zum Einkaufswagen und zur Kasse nicht wahrnimmt, loggt er sich mittels Single Sign-On nur einmal ein. Die beteiligten Systeme authentifizieren den eingeloggten Benutzer anhand seiner Single Sign-On Session. Detaillierte Informationen über OpenID Connect und Single Sign-On findet ihr hier . In diesem Artikel fokussiere ich mich auf das Anwendungs-System, welches zur Benutzer-Authentifizierung den firmeneigenen OpenID Identity Provider verwendet. Bevor wir uns die Implementierung...