Branches in Git: git branch erstellen, wechseln und löschen
Ein Branch in Git ist ein leichtgewichtiger Zeiger auf einen Commit, und HEAD zeigt, auf welchem Branch Sie sich gerade befinden. git branch listet, erstellt, benennt um und löscht Branches, git switch wechselt zwischen ihnen; git switch -c name erstellt einen Branch und wechselt sofort dorthin.
Was ist ein Branch in Git?
Ein Branch in Git ist keine Kopie des Projekts, sondern eine kleine Datei mit dem Hash eines einzigen Commits. Einen Branch zu erstellen dauert Sekundenbruchteile und kostet kaum Speicherplatz, weil Git nichts dupliziert: Alle Branches verweisen auf dieselben Objekte in der Datenbank des Repositorys. Wenn Sie committen, rückt der Zeiger des aktuellen Branches einfach auf den neuen Commit vor.
Das verändert den Umgang mit Branches. Man muss sie weder fürchten noch sparsam einsetzen: Ein eigener Branch für jede Aufgabe, jeden Bugfix oder jedes Experiment ist gängige Praxis. Scheitert ein Experiment, wird der Branch gelöscht, und die Haupthistorie bleibt sauber.
Dass ein Branch eine Datei ist, können Sie selbst sehen:
$ cat .git/refs/heads/main
8b7d4e2a9f1c0d3e5b6a7c8d9e0f1a2b3c4d5e6f
(In großen Repositorys ist ein Teil der Referenzen in .git/packed-refs gepackt, die Datei kann also fehlen — am Prinzip ändert das nichts.)
HEAD in Git: Wo Sie gerade sind
HEAD ist ein Zeiger auf das, was gerade in Ihrem Arbeitsverzeichnis „ausgecheckt“ ist. Normalerweise zeigt HEAD nicht auf einen Commit, sondern auf einen Branch:
$ cat .git/HEAD
ref: refs/heads/main
Die Kette sieht so aus: HEAD → main → Commit. Ein neuer Commit erhält als Elternteil den Commit, auf den HEAD zeigt; danach verschiebt Git den Branch, auf den HEAD verweist. Genau deshalb „landen“ Commits im aktuellen Branch.
Wechseln Sie direkt zu einem Commit oder Tag (git switch --detach v1.0 oder git checkout 3f2a1c9), zeigt HEAD unmittelbar auf einen Commit. Dieser Zustand heißt detached HEAD. Code darin anzusehen ist ungefährlich, aber neue Commits gehören zu keinem Branch und gehen nach einem Wechsel leicht verloren. Wenn Sie angefangen haben, etwas zu ändern, erstellen Sie direkt dort einen Branch: git switch -c fix-from-old-version.
In Ausdrücken eignet sich HEAD gut als Bezugspunkt: HEAD~1 ist der vorherige Commit, HEAD~3 liegt drei Commits zurück, HEAD^2 ist der zweite Elternteil eines Merge-Commits.
Branches anzeigen: git branch
git branch # lokale Branches, der aktuelle ist mit * markiert
git branch -v # zusätzlich der letzte Commit jedes Branches
git branch -vv # zusätzlich Upstream und Vorsprung/Rückstand
git branch -r # Remote-Branches (origin/...)
git branch -a # alle Branches
git branch --show-current # nur der Name des aktuellen Branches
Beispielausgabe von git branch -vv:
feature/login 4c1e2d7 [origin/feature/login: ahead 2] Login-Formular
* main 8b7d4e2 [origin/main] README aktualisieren
old-spike 1a9b3c0 Experiment mit Cache
Man sieht: In feature/login liegen zwei noch nicht gepushte Commits, main stimmt mit dem Server überein, und old-spike hat überhaupt kein Gegenstück auf dem Server.
Zum Filtern helfen git branch --merged (bereits in den aktuellen Branch gemergt — Kandidaten zum Löschen), git branch --no-merged (noch nicht gemergt) und git branch --list 'feature/*' (nach Muster).
Git Branch erstellen
Es gibt zwei Wege. git branch erstellt einen Branch, lässt Sie aber auf dem aktuellen:
git branch feature/login # vom aktuellen Commit
git branch hotfix v1.2.0 # von einem Tag
git branch review 3f2a1c9 # von einem bestimmten Commit
Häufiger will man einen Branch erstellen und gleich dorthin wechseln. Dafür gibt es git switch -c (seit Git 2.23) oder das ältere Äquivalent git checkout -b:
git switch -c feature/login
git switch -c hotfix origin/main # neuer Branch vom aktuellen Stand des Servers
Eine gute Gewohnheit: Vor dem Anlegen eines Aufgaben-Branches die Basis aktualisieren — git fetch, dann git switch -c feature/x origin/main. So beginnt der Branch mit aktuellem Code und nicht mit Ihrem lange nicht aktualisierten lokalen main.
Wie man Branches benennt
Bewährte Konventionen in Teams: ein Präfix nach Art der Arbeit und eine kurze Beschreibung mit Bindestrichen — feature/user-avatar, fix/login-timeout, chore/update-deps, manchmal mit Ticketnummer: feature/SHOP-142-cart. Nicht erlaubt sind Leerzeichen, ~ ^ : ? * [, zwei Punkte hintereinander und die Endung .lock.
Branch wechseln: git switch
git switch main # zu einem vorhandenen Branch wechseln
git switch - # zurück zum vorherigen Branch
git switch feature/login # gibt es lokal keinen, aber origin/feature/login,
# erstellt Git einen lokalen Branch und verknüpft ihn
Beim Wechsel ersetzt Git die Dateien im Arbeitsverzeichnis durch die Version aus dem Ziel-Branch. Nicht committete Änderungen nehmen Sie mit, sofern sie nicht mit dem Ziel-Branch kollidieren. Bei einem Konflikt verweigert Git den Wechsel:
error: Your local changes to the following files would be overwritten by checkout:
app.js
Please commit your changes or stash them before you switch branches.
Lösungen: committen, mit git stash zwischenspeichern (später mit git stash pop zurückholen) oder die Änderungen bewusst mit einem Merge-Versuch mitnehmen: git switch -m main. Das Flag --discard-changes verwirft die Änderungen — nutzen Sie es nur, wenn Sie sie sicher nicht mehr brauchen.
Warum git switch und nicht checkout? Checkout kann sowohl Branches wechseln als auch Dateien überschreiben, und dabei passieren leicht Fehler. Switch macht nur eins — es arbeitet mit Branches und ist deshalb sicherer. Einen ausführlichen Vergleich von checkout, switch und restore finden Sie in einem eigenen Artikel.
Branch umbenennen
git branch -m new-name # den aktuellen umbenennen
git branch -m old-name new-name # einen beliebigen umbenennen
git branch -M main # dasselbe, überschreibt einen vorhandenen Branch
War der Branch schon auf dem Server, gilt die Umbenennung nur lokal. Pushen Sie den neuen und löschen Sie den alten:
git push -u origin new-name
git push origin --delete old-name
Git Branch löschen
git branch -d feature/login # löscht nur, wenn der Branch gemergt ist
git branch -D old-spike # löscht erzwungen
git push origin --delete feature/login # auf dem Server löschen
-d schützt vor Arbeitsverlust: Enthält der Branch Commits, die im aktuellen Branch (oder dessen Upstream) fehlen, verweigert Git mit der Meldung „The branch 'x' is not fully merged“. -D löscht ohne Rückfrage. Den aktuellen Branch können Sie nicht löschen — wechseln Sie zuerst auf einen anderen.
Zu viel gelöscht? Commits verschwinden nicht sofort. Suchen Sie den Hash des letzten Commits des Branches in git reflog und stellen Sie ihn wieder her: git branch old-spike 1a9b3c0.
Veraltete Verweise auf Remote-Branches, die es auf dem Server nicht mehr gibt, räumt git fetch --prune auf.
Lokalen Branch mit Remote-Branch verknüpfen
Ein lokaler Branch kann einen Upstream haben — einen Remote-Branch, mit dem er verglichen und synchronisiert wird. Er sorgt dafür, dass git push und git pull ohne Argumente funktionieren und git status „ahead/behind“ anzeigt.
git push -u origin feature/login # beim ersten Push
git branch --set-upstream-to=origin/main main # für einen bestehenden Branch
git branch --unset-upstream # Verknüpfung entfernen
Branches mergen: kurz erklärt
Branches erstellt man, um sie später zusammenzuführen. Ist die Arbeit fertig, wechseln Sie in den Ziel-Branch und mergen Ihren hinein:
git switch main
git merge feature/login
Hat sich main seit dem Anlegen des Branches nicht weiterbewegt, macht Git einen Fast-Forward: Es verschiebt einfach den Zeiger von main auf den letzten Commit des Branches, ohne Merge-Commit. Haben beide Branches neue Commits, folgt ein Three-Way-Merge: Git findet den gemeinsamen Vorfahren, vergleicht beide Seiten und erstellt einen Merge-Commit mit zwei Eltern. In Teams wird meist per Pull Request auf dem Server gemergt, lokal holt man nur das aktuelle main.
Spickzettel für Branches
| Aufgabe | Befehl |
|---|---|
| Branches auflisten | git branch -vv |
| Branch erstellen | git branch name |
| Erstellen und wechseln | git switch -c name |
| Wechseln | git switch name |
| Zurückwechseln | git switch - |
| Umbenennen | git branch -m alt neu |
| Gemergten löschen | git branch -d name |
| Erzwungen löschen | git branch -D name |
| Auf dem Server löschen | git push origin --delete name |
| Löschbare Branches finden | git branch --merged |
| Gelöschten wiederherstellen | git reflog, dann git branch name hash |
Typische Anfängerfehler
- Direkt in main arbeiten. Sind Commits schon gemacht, aber nicht gepusht, erstellen Sie an der aktuellen Stelle einen Branch (
git branch feature/x) und setzen dannmainauf den Serverstand zurück:git reset --hard origin/main(prüfen Sie vorher, dass alles committet ist). - Branch von veraltetem main. Zuerst
git fetch, den Branch dann vonorigin/mainerstellen. - Commits im detached HEAD. Vor dem Wechsel einen Branch erstellen; sind Sie schon gewechselt, finden Sie die Commits in
git reflog. - Langlebige Branches. Je länger ein Branch getrennt lebt, desto schmerzhafter der Merge. Holen Sie regelmäßig
mainnach und mergen Sie Ihre Arbeit in kleinen Portionen.
Branches in der Teamarbeit
Die Abläufe in Teams unterscheiden sich, aber fast überall begegnet man einem von zwei Modellen. Bei GitHub Flow gibt es einen langlebigen Branch main, der jederzeit auslieferbar ist, und kurze Feature-Branches, die nach Review und CI-Prüfungen per Pull Request gemergt werden. Git Flow ergänzt develop, Release- und Hotfix-Branches; das Modell ist schwergewichtiger und passt zu Produkten mit seltenen, versionierten Releases.
Unabhängig vom Modell gelten gemeinsame Regeln: ein Branch — eine Aufgabe, ein Branch lebt Tage, nicht Monate, vor dem Pull Request ist der Branch auf dem aktuellen main-Stand, nach dem Merge wird er lokal und auf dem Server gelöscht. Der Haupt-Branch wird über die Repository-Einstellungen geschützt: Direkter Push und Force-Push sind verboten, gemergt wird nur nach Review.
Branch-Historie anzeigen
Wie Branches zueinander stehen, versteht man am einfachsten am Graphen: git log --oneline --graph --all zeichnet alle Branches und ihre Abzweigungen direkt im Terminal. Um Commits zu sehen, die im Branch sind, aber noch nicht in main, verwenden Sie git log main..feature/login, für die Unterschiede in Dateien git diff main...feature/login (drei Punkte vergleichen mit dem gemeinsamen Vorfahren, zeigen also nur die Änderungen des Branches selbst).
Fazit
Ein Branch in Git ist ein günstiger Zeiger auf einen Commit, HEAD ist ein Zeiger auf den aktuellen Branch. git branch verwaltet Branches (auflisten, erstellen, umbenennen, löschen), git switch wechselt zwischen ihnen, und git switch -c erledigt beides auf einmal. Branches, HEAD, Fast-Forward und Three-Way-Merge werden im Git-Kurs an praktischen Beispielen erklärt.
Häufige Fragen
Wie viele Branches kann man in Git erstellen?
Praktisch beliebig viele: Jeder Branch ist eine Referenz von wenigen Dutzend Bytes, Speichergrenzen gibt es also keine.
Werden Commits zusammen mit dem Branch gelöscht?
Nicht sofort. Commits, auf die nichts mehr verweist, bleiben noch eine Weile erhalten und sind über git reflog erreichbar, bis die Garbage Collection sie entfernt (standardmäßig frühestens nach 30 Tagen für nicht erreichbare Reflog-Einträge).
Wie finde ich heraus, von welchem Branch der aktuelle abgezweigt wurde?
Git speichert das nicht: Ein Branch kennt nur seinen Commit. Den gemeinsamen Vorfahren mit main findet git merge-base HEAD main.
Was ist der Unterschied zwischen Branch und Tag?
Ein Branch bewegt sich mit jedem neuen Commit weiter, ein Tag ist dauerhaft an einen Commit gebunden und markiert Releases.
Warum main und nicht master?
Das ist nur der Name des Standard-Branches. Viele Dienste sind auf main umgestiegen; für neue Repositorys legen Sie ihn mit git config --global init.defaultBranch main fest.
Dieses Thema wird im Kurs „Git vom Anfänger zum versierten Entwickler“ ausführlich mit Praxis behandelt.
Zum Kurs