Holt git pull alle Branches? Was der Befehl wirklich aktualisiert

Programmierung

git pull holt neue Commits vom Server – aber welche? Nur den Branch, auf dem Sie gerade stehen, oder wirklich alle? Diese Verwechslung führt regelmäßig dazu, dass lokale Feature-Branches wochenlang veraltet sind, obwohl „ja ständig gepullt“ wurde. Dieser Text klärt, was git pull aktualisiert, warum der Fetch-Teil mehr holt als der Merge-Teil verarbeitet, und wie Sie mit einem wiederholbaren Ablauf wirklich alle Branches auf Stand bringen.

Was git pull wirklich macht: fetch + merge

git pull ist kein eigenständiger Befehl, sondern eine Abkürzung für zwei Schritte:

git fetch        # neue Commits vom Remote herunterladen
git merge        # sie in den aktuellen Branch integrieren

Standardmäßig wird gemergt; mit git pull --rebase (oder der Einstellung pull.rebase true) wird stattdessen rebased. Der entscheidende Teil steckt aber im ersten Schritt – und genau der wird meist falsch verstanden.

Holt der Fetch alle Branches? Ja. Der Merge? Nein.

Hier liegt der Kern der Frage. git fetch lädt per Standard-Refspec +refs/heads/*:refs/remotes/origin/* alle Branches des Remotes herunter und aktualisiert die zugehörigen Remote-Tracking-Branches (origin/main, origin/develop, origin/feature-x …). Da git pull intern genau dieses Fetch ausführt, sind nach einem Pull tatsächlich alle origin/*-Referenzen aktuell.

Der zweite Schritt, der Merge, betrifft dagegen nur einen einzigen Branch: den, auf dem Sie gerade stehen. Ihre anderen lokalen Branches (main, develop, …) bleiben unangetastet, bis Sie sie auschecken und selbst aktualisieren.

Kurz: git pull holt die Daten aller Branches, integriert aber nur einen. Deshalb kann git log origin/develop schon neue Commits zeigen, während Ihr lokaler develop noch alt ist.

git pull —all – warum es selten hilft

Naheliegend wäre git pull --all. Das --all wird jedoch nur an den Fetch-Schritt durchgereicht und bedeutet „von allen Remotes holen“, nicht „alle Branches mergen“. Der Merge betrifft weiterhin ausschließlich den aktuellen Branch. In einem Projekt mit nur einem Remote – dem Normalfall – ändert git pull --all gegenüber git pull praktisch nichts.

Alle Branches wirklich aktualisieren

Schritt 1: Alle Remote-Branches holen

git fetch --all --prune

--all holt von allen Remotes, --prune entfernt Remote-Tracking-Branches, die auf dem Server bereits gelöscht wurden. Danach sind alle origin/* auf Stand – noch ohne jede Änderung an Ihrem Arbeitsverzeichnis. Wer nur einen Remote hat, kann ebenso git remote update --prune verwenden.

Schritt 2: Den aktuellen Branch nachziehen

git pull --ff-only

--ff-only lässt den Pull nur zu, wenn er ein reiner Fast-Forward ist. Gibt es divergierende Commits, bricht der Befehl ab, statt einen unerwarteten Merge-Commit zu erzeugen – deutlich sicherer als ein blankes git pull. Mehr zum Unterschied im Beitrag git fetch vs. git pull.

Schritt 3: Weitere Branches ohne Checkout aktualisieren

Einen nicht ausgecheckten Branch können Sie direkt per Fetch-Refspec fast-forwarden, ohne ihn zu wechseln:

git fetch origin main:main develop:develop

Das setzt die lokalen main und develop auf den Stand von origin/main bzw. origin/develop. Wichtig: Das funktioniert nur, wenn die Aktualisierung ein Fast-Forward ist und der Branch nicht gerade ausgecheckt ist. Den aktuellen Branch lehnt Git mit refusing to fetch into branch … checked out ab – dafür ist Schritt 2 zuständig.

Ein robustes Skript für alle lokalen Branches

Das oft kursierende Einzeiler-Skript (for branch in $(git branch …); git checkout; git pull) hat drei Schwächen: Es scheitert bei ungespeicherten Änderungen, kann ungewollte Merge-Commits erzeugen und lässt Sie am Ende auf dem falschen Branch stehen. Diese Variante vermeidet das:

#!/usr/bin/env bash
set -e
git fetch --all --prune
start=$(git symbolic-ref --short HEAD)   # aktuellen Branch merken
trap 'git checkout --quiet "$start"' EXIT   # auch bei Abbruch zurückkehren

for branch in $(git for-each-ref --format='%(refname:short)' refs/heads/); do
    # nur Branches mit konfiguriertem Upstream anfassen
    if git rev-parse --abbrev-ref "$branch@{upstream}" >/dev/null 2>&1; then
        git checkout --quiet "$branch"
        git merge --ff-only --quiet || echo "  übersprungen: $branch (kein Fast-Forward)"
    fi
done

git for-each-ref liefert die Branchnamen sauber – ohne das *-Zeichen des aktiven Branches und ohne führende Leerzeichen, an denen der naive git branch | sed-Ansatz oft scheitert. --ff-only schützt vor unbeabsichtigten Merges: Branches, die vom Remote abgewichen sind, werden übersprungen und angezeigt, statt das Skript zu stoppen. Da nach jedem Merge ohne Argumente automatisch der konfigurierte Upstream des jeweiligen Branches herangezogen wird, brauchen Sie keinen zusätzlichen Fetch pro Durchlauf. Der trap auf EXIT sorgt dafür, dass Sie selbst dann auf dem Ausgangsbranch landen, wenn ein Checkout mittendrin scheitert – etwa wegen ungespeicherter Änderungen.

Typische Fehler und Lösungen

  • Your local changes would be overwritten by checkout – ungespeicherte Änderungen blockieren den Branch-Wechsel. Vorher git stash (und danach git stash pop) oder die Änderungen committen. Siehe auch Git-Änderungen verwerfen.
  • refusing to fetch into branch … checked out – Sie versuchen, den aktuell ausgecheckten Branch per Refspec zu aktualisieren. Nutzen Sie dafür git pull --ff-only statt git fetch origin branch:branch.
  • ! [rejected] main -> main (non-fast-forward) – die Aktualisierung wäre kein Fast-Forward, weil Ihr lokaler Branch eigene Commits hat. Auschecken und bewusst git merge oder git rebase ausführen, statt mit + zu erzwingen.
  • origin/* aktualisiert sich nicht – prüfen Sie die Refspec mit git config --get remote.origin.fetch. Fehlt +refs/heads/*:refs/remotes/origin/*, wurde das Repository vermutlich flach (--depth) oder mit --single-branch geklont.

FAQ

Aktualisiert git fetch mein Arbeitsverzeichnis? Nein. git fetch verändert nur die Remote-Tracking-Branches (origin/*) und lädt die zugehörigen Objekte herunter. Ihre Dateien und lokalen Branches bleiben unberührt, bis Sie mergen, rebasen oder auschecken.

Wie sehe ich, welche lokalen Branches hinterherhinken? git branch -vv zeigt zu jedem Branch den Upstream sowie Markierungen wie [ahead 2, behind 5]. So erkennen Sie auf einen Blick, welcher Branch ein git pull --ff-only braucht.

Kann ich wirklich alle Branches mit einem Befehl mergen? Nicht mit einem eingebauten Git-Befehl – ein Merge betrifft immer nur den ausgecheckten Branch. Sie brauchen entweder die Fetch-Refspec-Methode aus Schritt 3 oder ein Skript wie oben. Zusatzwerkzeuge bündeln das, gehören aber nicht zum Git-Standard.