Branching Basics: Lernzweige und Features sauber trennen
Lernartikel zu Git-Branching für Android-Entwicklung: Branch anlegen, wechseln, mergen und Konflikte vermeiden.
Sobald du anfängst, ernsthaft an einer Android-App zu arbeiten, willst du Dinge ausprobieren, ohne deinen funktionierenden Stand kaputtzumachen. Genau dafür sind Branches da. Sie sind der wichtigste Hebel, um Lernexperimente, neue Features und Bugfixes voneinander zu trennen, ohne jedes Mal Angst um deinen letzten guten Build zu haben. In diesem Artikel lernst du, was ein Branch wirklich ist, wie branch, switch und merge zusammenspielen und welche Routinen sich für deine Android-Projekte mit Kotlin, Jetpack und Compose bewährt haben.
Was ist das?
Ein Branch in Git ist nichts weiter als ein beweglicher Zeiger auf einen einzelnen Commit. Du kannst ihn dir wie ein Lesezeichen vorstellen, das mitwandert, sobald du neue Commits erzeugst. Der bekannteste Branch heißt in modernen Projekten meistens main. Er repräsentiert deinen offiziellen, funktionierenden Stand. Alle anderen Branches sind Abzweigungen davon und haben üblicherweise einen klaren Zweck: ein neues Feature, ein Experiment, ein Bugfix oder ein Release.
Im Android-Alltag bedeutet das: Solange du auf main arbeitest, baust du am gemeinsamen Fundament. Sobald du etwas Riskantes ausprobierst, etwa eine neue Compose-Animation, einen Wechsel der Navigationsbibliothek oder den ersten Versuch mit Kotlin Flow, gehörst du auf einen eigenen Branch. Dort kannst du dich austoben, ohne die Build-Pipeline, deine Mitlernenden oder deinen eigenen Lernfortschritt zu blockieren. Wenn das Experiment scheitert, wirfst du den Branch weg. Wenn es funktioniert, integrierst du ihn zurück.
Wichtig: Ein Branch erzeugt keine Kopie deines Projekts auf der Festplatte. Git verwaltet die Versionen intern als Snapshots. Branches sind deshalb extrem günstig zu erstellen und zu löschen. Diese Leichtigkeit ist eine zentrale Idee. Du sollst Branches benutzen, ohne nachzudenken, ob sich der Aufwand lohnt.
In der Roadmap steht „Branching Basics” bewusst früh, weil fast alle späteren Themen, von Architektur über Tests bis zum Release, davon profitieren, wenn du sauber mit Branches umgehst. Wer das hier verinnerlicht, verliert später keine Stunden mit der Frage, warum auf einmal alles kaputt ist.
Wie funktioniert es?
Branching besteht im Kern aus drei Operationen, die du immer wieder kombinierst: einen Branch anlegen, zwischen Branches wechseln und Branches zusammenführen.
Branch anlegen und wechseln
In aktuellen Git-Versionen sind dafür zwei Kommandos relevant:
git branch <name>legt einen neuen Branch an, lässt dich aber auf dem bisherigen Branch.git switch <name>wechselt auf einen vorhandenen Branch.git switch -c <name>legt einen neuen Branch an und wechselt direkt dorthin.
Das ältere git checkout kann beides, ist aber gleichzeitig für ganz andere Dinge zuständig (etwa Dateien verwerfen). Deshalb empfiehlt es sich, im Alltag switch und restore zu verwenden. Das macht die Befehle eindeutiger und reduziert Tippfehler mit teuren Folgen.
Wenn du git switch -c feature/compose-onboarding ausführst, passiert Folgendes: Git erstellt einen neuen Branch-Zeiger, der auf deinen aktuellen Commit zeigt, und macht ihn zu deinem aktiven Branch. Alle weiteren Commits hängen ab jetzt an diesem Zeiger. Dein main bleibt unberührt.
Der HEAD-Zeiger
Git führt zusätzlich einen speziellen Zeiger namens HEAD. Er beschreibt, „wo du gerade stehst”. Auf einem normalen Branch zeigt HEAD auf den Branch-Namen, der wiederum auf den letzten Commit zeigt. Wenn du commitest, bewegen sich Branch und HEAD gemeinsam. Wenn du git switch benutzt, springt HEAD auf einen anderen Branch und dein Arbeitsverzeichnis wird automatisch an dessen Stand angeglichen.
Dieses Modell zu verstehen ist die halbe Miete. Viele Verwirrungen entstehen, weil Lernende denken, ein Branch sei ein „Ordner mit Code”. Tatsächlich ist es nur ein Name plus eine Liste von Commits, die du über Eltern-Verweise erreichst.
Mergen
Sobald deine Änderungen auf dem Feature-Branch fertig sind, willst du sie in main zurückbringen. Das geht mit git merge. Der typische Ablauf:
- Du wechselst auf den Zielbranch:
git switch main. - Du holst den aktuellen Stand vom Server:
git pull --ff-only. - Du führst zusammen:
git merge feature/compose-onboarding.
Git versucht jetzt, die Commits deines Feature-Branches in main einzubauen. Es gibt zwei Hauptfälle:
- Fast-Forward-Merge:
mainhat sich seit dem Abzweigen nicht weiterbewegt. Git verschiebt einfach denmain-Zeiger nach vorn auf den letzten Commit deines Feature-Branches. Es entsteht kein zusätzlicher Commit. - Drei-Wege-Merge: Beide Branches haben neue Commits. Git baut einen sogenannten Merge-Commit, der zwei Eltern-Commits hat, und kombiniert die Änderungen. Wenn dieselbe Stelle in beiden Branches geändert wurde, gibt es Konflikte, die du manuell lösen musst.
In professionellen Android-Projekten wird der Merge oft nicht lokal ausgeführt, sondern über einen Pull Request auf GitHub, GitLab oder Bitbucket. Das Prinzip bleibt aber identisch.
Branches und Remote
Lokale Branches existieren erst einmal nur auf deinem Rechner. Mit git push -u origin feature/compose-onboarding veröffentlichst du sie auf dem Server und verknüpfst sie als Tracking-Branch. Danach reicht ein einfaches git push. Dieses Detail ist entscheidend, sobald du im Team arbeitest oder dein Lernprojekt in einem öffentlichen Repository sicherst.
In der Praxis
Stell dir vor, du arbeitest dich gerade durch den Kurs „Android Basics with Compose” und willst zwei Dinge gleichzeitig tun: ein neues Onboarding mit Compose ausprobieren und einen kleinen Bug in der bestehenden Detail-Ansicht beheben. Wenn du beides auf main machst, vermischen sich die Änderungen und du wirst sie weder leicht testen noch einzeln rückgängig machen können.
Mit Branches sieht der Ablauf so aus:
// Pseudocode-Kommentar: Reihenfolge der Git-Befehle in deinem Terminal.
// Ausgangspunkt: sauberer main-Branch, alles committet.
# 1. Sicherstellen, dass main aktuell ist
git switch main
git pull --ff-only
# 2. Feature-Branch fürs Onboarding anlegen
git switch -c feature/compose-onboarding
# ... Code schreiben, committen ...
git add app/src/main/java/de/androidcoden/onboarding/OnboardingScreen.kt
git commit -m "feat(onboarding): add first Compose screen"
# 3. Zurück zu main, separaten Bugfix-Branch starten
git switch main
git switch -c fix/detail-crash
# ... Bug beheben, Tests anpassen, committen ...
git commit -am "fix(detail): guard null state from ViewModel"
# 4. Fix mergen, sobald er getestet ist
git switch main
git merge --no-ff fix/detail-crash
git push
# 5. Onboarding später separat fertigstellen und mergen
git switch feature/compose-onboarding
# ... weiterarbeiten ...
Beachte den --no-ff-Flag im Merge des Bugfixes. Damit erzwingst du einen echten Merge-Commit, auch wenn ein Fast-Forward möglich wäre. Das macht die History später besser lesbar, weil du auf einen Blick siehst, welche Commits zu welchem Branch gehörten. Für reine Lernprojekte ist das Geschmackssache, in Teams ist es oft Standard.
Eine einfache Entscheidungsregel
Bevor du anfängst zu programmieren, stelle dir eine Frage: „Würde es weh tun, wenn diese Änderung morgen wieder rausfliegt?” Wenn die Antwort „ja” oder „vielleicht” ist, gehört die Arbeit auf einen eigenen Branch. Das gilt insbesondere, wenn du:
- eine neue Bibliothek wie Hilt, Room oder Ktor evaluierst,
- größere Refactorings an einer ViewModel-Schicht planst,
- mit einer neuen Compose-API experimentierst,
- oder Migrationen zwischen Versionen wie AndroidX testest.
Für triviale Korrekturen wie Tippfehler in Strings oder einen falsch benannten Drawable kannst du auch direkt auf main arbeiten, solange du allein entwickelst. Sobald andere mitlesen, ist ein kurzer Branch trotzdem sauberer.
Typische Stolperfalle: Arbeit auf dem falschen Branch
Eine der häufigsten Fehlerquellen am Anfang ist, dass du Stunden auf main programmierst und erst beim Pushen merkst, dass dein Stand auf einem Feature-Branch landen sollte. Die Rettung sieht so aus:
# Du bist auf main mit nicht gepushten Commits, die woanders hingehören.
git switch -c feature/compose-onboarding
# Jetzt liegen die Commits auf dem neuen Branch.
git switch main
git reset --hard origin/main
Den letzten Befehl benutzt du nur, wenn du absolut sicher bist, dass auf main nichts Wertvolles mehr liegt. git reset --hard wirft lokale Änderungen weg. Erst Branch sichern, dann zurücksetzen, niemals andersherum.
Ein zweiter Klassiker: Konflikte in app/build.gradle.kts oder gradle/libs.versions.toml, weil zwei Branches gleichzeitig Abhängigkeiten ändern. Dagegen hilft, große Bibliotheks-Updates in eigene, kurzlebige Branches zu legen und früh zu mergen, statt sie wochenlang offen zu lassen.
Fazit
Branches sind das Werkzeug, das deinen Code-Alltag von „Daumen drücken und hoffen” zu „bewusst experimentieren” umstellt. Du legst sie an, wenn du etwas Riskantes ausprobierst, du wechselst zwischen ihnen, wenn du parallel an verschiedenen Dingen arbeitest, und du mergst sie, wenn das Ergebnis verlässlich ist. Wenn du gerade mit Android und Compose anfängst, übe diese drei Schritte bewusst: Lege für die nächste Übung des Kurses einen Feature-Branch an, baue ein kleines Stück Funktionalität, schaue dir mit git log --oneline --graph --all an, wie deine History tatsächlich aussieht, und mergst den Branch mit --no-ff zurück nach main. Verifiziere dein Verständnis, indem du den Stand vor und nach dem Merge in Android Studio baust und im Emulator startest. Erst wenn du diesen Kreislauf zwei- oder dreimal sauber durchgezogen hast, ist „Branching Basics” wirklich verinnerlicht und du bist bereit für die nächsten Roadmap-Themen rund um Code-Review, Tests und Release-Prozesse.